Get the corresponding type in the object, and then traverse the array of push objects, but I can't think of a better way to solve the desired result below.
I want a good return as follows:
[{
"id": 1,
"type": "one",
"name": ["apple","apricot"]
},
{
"id": 3,
"type": "two",
"name": ["avocado"]
}]
var result = [{
"id": 1,
"type": "one",
"name": "apple"
}, {
"id": 2,
"type": "one",
"name": "apricot"
},
{
"id": 3,
"type": "two",
"name": "avocado"
}
]
Array.prototype.unique = function() {
var hash = {},
len = this.length,
result = [];
for (var i = 0; i < len; i++) {
if (!hash[this[i].type]) {
result.push(this[i].type);
hash[this[i].type] = true;
}
}
return result;
}
console.log(result)
console.log(result.unique())
var cArr = result.unique()
var arr = []
cArr.forEach(function(prop) {
result.map(function(item) {
if (prop == item.type) {
console.log(item)
arr.push({
...item,
[`user_${item.id}`]: item.user,
})
}
})
})
console.log(arr)
You can do this with reduce quite easily:
var input = [
{ id: 1, type: "one", name: "apple"},
{ id: 2, type: "one", name: "apricot" },
{ id: 3, type: "two", name: "avocado" }
];
// Make sure `unique` doesn't already exist on the Array prototype
if (!('unique' in Array.prototype)) {
Array.prototype.unique = function () {
// iterate over the array
const temp = this.reduce((acc, current) => {
// Desstructure the id, type, and name from the current object
const { id, type, name } = current;
// If an key with the value of `type` doesn't exist
// on the accumulator, add a new object with name set
// to an empty array
acc[type] = acc[type] || { id, type, name: [] };
// Push the name in the current object to the name array
acc[type].name.push(name);
// Return the accumulator for the next iteration
return acc;
// Note: the initial accumulator value is an object
}, {});
// Then simply return the values from the accumulated object
return Object.values(temp);
}
}
console.log(input.unique())
I am trying to group items an array of items by a property and then reindex the result starting from 0.
The following function returns a grouped set of items.
groupItemBy(array, property) {
let hash = {},
props = property.split('.');
for (let i = 0; i < array.length; i++) {
let key = props.reduce( (acc, prop) => {
return acc && acc[prop];
}, array[i]);
if (!hash[key]) hash[key] = [];
hash[key].push(array[i]);
}
return hash;
}
The result is an array of arrays, and something like:
[{
"1193312":[
{
"description":"Item 1",
"number": "1193312"
}
],
"1193314":[
{
"itemDesc":"Item 2"},
"number": "1193314"
{
"description":"Item 3",
"number": "1193314"
}
],
etc...
}]
From here I'd like to map 1193312 to 0, and 1193314 to 1, etc.
I tried .filter(val => val) on the result, but that seemed to have no effect.
You need to use an intermediate key replacement:
function groupItemBy(array, property) {
let hash = {}
let props = property.split('.')
let keys = []
for (let i = 0; i < array.length; i++) {
let key = props.reduce((acc, prop) => {
return acc && acc[prop];
}, array[i]);
let subst = keys.indexOf(key)
if (subst === -1) {
keys.push(key)
subst = keys.length - 1
}
if (!hash[subst]) hash[subst] = [];
hash[subst].push(array[i]);
}
return hash;
}
[ https://jsfiddle.net/05t9141p/ ]
You could use map for the array part, and Object.values and reduce for the renumber part.
const data = [{
"1193312":[
{
"time":"2018-02-20",
"description":"Item 1",
"number": "1193312"
}
],
"1193314":[
{
"time":"2018-02-21",
"itemDesc":"Item 2",
"number": "1193314"
},{
"time":"2018-02-21",
"description":"Item 3",
"number": "1193314"
}
]
}];
const renumbered =
data.map((m) => Object.values(m).reduce((a,v,ix) => (a[ix] = v, a), {}));
console.log(renumbered);
var data = [{
"1193312":[
{
"description":"Item 1",
"number": "1193312"
}
],
"1193314":[
{
"itemDesc":"Item 2",
"number": "1193314"},
{
"description":"Item 3",
"number": "1193314"
}
]
}]
var newData = Object.keys(data[0]).map(function(key,index){
var newObj={};
newObj[index] = data[0][key];
return newObj;
});
console.log(newData);
If you can use ES6:
var arr = [{
"1193312":[
{
"time":"2018-02-20",
"description":"Item 1"
}
],
"1193314":[
{
"time":"2018-02-21",
"itemDesc":"Item 2"},
{
"time":"2018-02-21",
"description":"Item 3"
}
]
}];
var data = arr[0];
var res = Object.entries(data).map(([key, value]) => ({[key]: value}));
console.log(res);
I have an array of objects:-
var arr1 = [{
"name": "A"
}, {
"name": "B"
}, {
"name": "C"
}, {
"name": "D"
}];
I want to add a new property to each element which are not present in the second array.
var arr2 = [C,D]
The resulted array should be:-
arr1 = [{
"name": "A",
"country":"USA"
}, {
"name": "B",
"country":"USA"
}, {
"name": "C"
}, {
"name": "D"
}];
Can any one tell me how to achieve that?
I want to add a new property to each element which are not present in the second array.
That completely changes the question you originally asked.
If the items are mutable, you'd just loop through the array adding the property to selected items. There are many ways to do that, such as forEach:
arr1.forEach(function(item) {
if (arr2.indexOf(item.name) === -1) {
item.country = "USA";
}
});
Live Example:
var arr1 = [{
"name": "A"
}, {
"name": "B"
}, {
"name": "C"
}, {
"name": "D"
}];
var arr2 = ["C", "D"];
arr1.forEach(function(item) {
if (arr2.indexOf(item.name) === -1) {
item.country = "USA";
}
});
console.log(arr1);
If they're immutable, you'd use map instead:
arr1 = arr1.map(function(item) {
if (arr2.indexOf(item.name) === -1) {
return /*...create item with `country = "USA"` here...*/;
} else {
return item;
}
});
Live Example:
var arr1 = [{
"name": "A"
}, {
"name": "B"
}, {
"name": "C"
}, {
"name": "D"
}];
var arr2 = ["C", "D"];
arr1 = arr1.map(function(item) {
if (arr2.indexOf(item.name) === -1) {
return {name: item.name, country: "USA"};
} else {
return item;
}
});
console.log(arr1);
Original answer: (to your original question)
You would loop over the resulting array adding the property. There are many ways to do that, such as forEach:
arr1.forEach(function(item) {
item.country = "USA";
});
Technically, you could make it a side-effect of your filter, like this:
var arr1 = arr1.filter(function(item){
if (arr2.indexOf(item.name) === -1) {
item.country = "USA";
return true;
};
return false;
});
BUT, side-effects in filter callbacks (and similar) are generally not a great idea. Unless you know that the resulting array (arr1) is hundreds of thousands of entries, the second pass keeps things simple by filtering and then modifying.
Use Array.forEach and add the property if the element is not present - by using the same comparison you were already using.
I have to merge 2 arrays with key value as follows:
array1 = [
{id:"123", data:[{id:"234",data:"hello"},{id:"345",data:"there"},{id:"xyz", data:"yo"}]},
{id:"456", data:[{id:"34",data:"test"},{id:"45",data:"test2"},{id:"yz", data:"test3"}]},
{id:"789", data:[{id:"23",data:"aaa"},{id:"34",data:"bbb"},{id:"xy", data:"ccc"}]}]
with
array2 = [
{id:"456", data:[{id:"45",data:"changed"},{id:"yz", data:"data"}]},
{id:"789", data:[{id:"456",data:"appended data"}]},
{id:"890", data:[{id:"456",data:"new data"}]}]
to produce something like
merged = [
{id:"123", data:[{id:"234",data:"hello"},{id:"345",data:"there"},{id:"xyz", data:"yo"}]},
{id:"456", data:[{id:"34",data:"test"},{id:"45",data:"changed"},{id:"yz", data:"data"}]},
{id:"789", data:[{id:"23",data:"aaa"},{id:"34",data:"bbb"},{id:"xy", data:"ccc"},{id:"456",data:"appended data"}]},
{id:"890", data:[{id:"456",data:"new data"}]}]
I've been trying this out for quite some time and can't get a solution that meets the scenario. Most of the solutions just do blind merging, not based on the id value. Tried using lodash mergeWith but didn't get the output needed. A Ramda solution is also acceptable.
Thanks,
This links could be helpful to you merge two arrays.
In this code snippet, i have tried to find the common objects between set1 and set2,if there are any i'm finding the unique properties and changing their content and also non existant properties in object2 and pushing it to object1
Check the following snippet.
var arr1 = [{
id: "123",
data: [{
id: "234",
data: "hello"
}, {
id: "345",
data: "there"
}, {
id: "xyz",
data: "yo"
}]
}, {
id: "456",
data: [{
id: "34",
data: "test"
}, {
id: "45",
data: "test2"
}, {
id: "yz",
data: "test3"
}]
}, {
id: "789",
data: [{
id: "23",
data: "aaa"
}, {
id: "34",
data: "bbb"
}, {
id: "xy",
data: "ccc"
}]
}]
var arr2 = [{
id: "456",
data: [{
id: "45",
data: "changed"
}, {
id: "yz",
data: "data"
}]
}, {
id: "789",
data: [{
id: "456",
data: "appended data"
}]
}, {
id: "890",
data: [{
id: "456",
data: "new data"
}]
}]
var arr3 = [];
for (var i in arr1) {
var shared = false;
for (var j in arr2)
if (arr2[j].id == arr1[i].id) {
shared = true;
// arr1[i].data.concat(arr2[j].data);
var set1 = pushproperties(arr1[i].data, arr2[j].data);
arr1[i].data = set1;
arr3.push(arr1[i]);
break;
}
if (!shared) {
arr3.push(arr1[i]);
arr3.push(arr2[j]);
}
}
function pushproperties(set1, set2) {
var filtered = false;
set2.forEach(function(item) {
filtered = set1.every(function(element) {
return element.id != item.id;
});
if (filtered) {
set1.push(item);
}
});
set1.forEach(function(item) {
set2.forEach(function(element) {
if (item.id == element.id) {
item.data = element.data;
}
});
});
return set1;
}
console.log(arr3);
Hope this helps
This a function the merges 2 arrays recursively using Array.prototype.reduce(). If it encounters items with the same id, and they have a data prop, which is an array, it merges them using the logic. If data is not an array, it's overridden by the last item instead.
function mergeArraysDeep(arr1, arr2) {
var unique = arr1.concat(arr2).reduce(function(hash, item) {
var current = hash[item.id];
if(!current) {
hash[item.id] = item;
} else if (Array.isArray(current.data)) {
current.data = mergeArraysDeep(current.data, item.data);
} else {
current.data = item.data;
}
return hash;
}, {});
return Object.keys(unique).map(function(key) {
return unique[key];
});
}
var array1 = [
{id:"123", data:[{id:"234",data:"hello"},{id:"345",data:"there"},{id:"xyz", data:"yo"}]},
{id:"456", data:[{id:"34",data:"test"},{id:"45",data:"test2"},{id:"yz", data:"test3"}]},
{id:"789", data:[{id:"23",data:"aaa"},{id:"34",data:"bbb"},{id:"xy", data:"ccc"}]}
];
var array2 = [
{id:"456", data:[{id:"45",data:"changed"},{id:"yz", data:"data"}]},
{id:"789", data:[{id:"456",data:"appended data"}]},
{id:"890", data:[{id:"456",data:"new data"}]}
];
var result = mergeArraysDeep(array1, array2)
console.log(result);
ES6 version that uses Map, Map.prototype.values(), and array spread:
const mergeArraysDeep = (arr1, arr2) => {
return [...arr1.concat(arr2).reduce((hash, item) => {
const current = hash.get(item.id);
if(!current) {
hash.set(item.id, item);
} else if (Array.isArray(current.data)) {
current.data = mergeArraysDeep(current.data, item.data);
} else {
current.data = item.data;
}
return hash;
}, new Map()).values()];
}
const array1 = [
{id:"123", data:[{id:"234",data:"hello"},{id:"345",data:"there"},{id:"xyz", data:"yo"}]},
{id:"456", data:[{id:"34",data:"test"},{id:"45",data:"test2"},{id:"yz", data:"test3"}]},
{id:"789", data:[{id:"23",data:"aaa"},{id:"34",data:"bbb"},{id:"xy", data:"ccc"}]}
];
const array2 = [
{id:"456", data:[{id:"45",data:"changed"},{id:"yz", data:"data"}]},
{id:"789", data:[{id:"456",data:"appended data"}]},
{id:"890", data:[{id:"456",data:"new data"}]}
];
const result = mergeArraysDeep(array1, array2)
console.log(result);
Finally this is what worked for me. Thanks to #Geeky for showing the way:
function mergeArrays(arr1, arr2) {
var arr3, arrIdx = [];
if (!arr1 || arr1.length ==0) return arr2
for (var i in arr1) {
var shared = false;
for (var j in arr2)
if (arr2[j].id == arr1[i].id) {
shared = true;
joined = _.mergeWith({},arr1[i],arr2[j], function (a,b) {
if (_.isArray(a)) return b.concat(a)})
arr3.push(joined);
break;
}
if (!shared) {
arr3.push(arr1[i]);
}
}
for (var k in arr2) {
if (arrIdx[k] !=k) arr3.push(arr2[k])
}
return arr3
}
With the following array;
var arr = [
{"name": "blah"},
{"version": "v1.0.0"},
...
]
I would like to create the following object with lodash;
var obj = {
"name": "blah",
"version": "v1.0.0",
...
}
P.S. Duplicates don't matter as there won't be any here.
Here is a solution using plain JavaScript.
References:
Object.assign can be used to concatenate Objects({}).
Array.prototype.reduce can be used to minimize the Array([]) values.
var arr = [{
"name": "blah"
}, {
"version": "v1.0.0"
}];
var obj = arr.reduce(function(o, v) {
return Object.assign(o, v);
}, {});
console.log(obj);
Why use lodash when you can do it in pure js?
var arr = [
{
"name": "blah"
},
{
"version": "v1.0.0"
}
]
var obj = arr.reduce(function(acc, val) {
var key = Object.keys(val)[0];
acc[key] = val[key];
return acc;
}, {})
console.log(obj)
Lodash implementation.
var arr = [{
"name": "name"
}, {
"version": "v1.0.0"
},{
"manager": "manager"
}];
var result = _.reduce(arr, function(object, value) {
return _.assign(object, value);
}, {});
console.log(result);