Related
I have an array containing objects where there is a rpId key in some of the objects. The goal is to separate/move the objects that return undefined to a separate array and remove them out of the first array.
e.g.:
results = [{id: 1}, {id: 2, rpId: 1076}, {id: 3}, {id: 4, rpId: 303}];
goal: results = [{id: 2, rpId: 1076}, {id: 4, rpId: 303}] and stations = [{id: 1}, {id: 3}]
My current approach can be seen below. As visible, I get a wrong array1 because it contains an object with a rpId, plus array2 returns the keys of the object and I'd like to read the entire object, not just the "undefined" of the key.
const array1 = [{id: 1}, {id: 2, rpId: 1076}, {id: 3}, {id: 4, rpId: 303}];
const array2 = [];
const mapping = array1.map((e) => e.rpId);
console.log("mapping",mapping);
mapping.forEach(function(elem, index){
elem === undefined ? array2.push(elem) && array1.splice(index, elem === undefined) && console.log(elem): console.log("defined", elem);
}),
console.log("1", array1); // [{ id: 2, rpId: 1076 }, { id: 3 }]
console.log("2", array2); // [undefined, undefined]
Just check if the rpId property is undefined in each element.
const array1 = [{id: 1}, {id: 2, rpId: 1076}, {id: 3}, {id: 4, rpId: 303}];
const array2 = [];
array1.forEach(function(elem, index){
if(elem.rpId === undefined)
array2.push(elem) && array1.splice(index, 1)
});
console.log(array1);
console.log(array2);
One can also use Array#filter or push elements into two separate arrays based on the condition for better performance.
const array1 = [{id: 1}, {id: 2, rpId: 1076}, {id: 3}, {id: 4, rpId: 303}];
const yes = [], no = [];
array1.forEach(elem=>(elem.rpId!==undefined?yes:no).push(elem));
console.log(yes);
console.log(no);
You can use filter too:
let results = [
{ id: 1 },
{ id: 2, rpId: 1076 },
{ id: 3 },
{ id: 4, rpId: 303 },
];
const stations = results.filter((c) => !c.rpId);
results = results.filter((c) => c.rpId);
console.log("stations", stations);
console.log("results", results);
const GiveItACreativeName = (arr) => {
const result = []
const stations = []
arr.forEach((el) => {
if('rpId' in el) result.push(el);
else stations.push(el);
});
return {result, stations}
}
console.log(
GiveItACreativeName([{id: 1}, {id: 2, rpId: 1076}, {id: 3}, {id: 4, rpId: 303}])
);
I have 2 arrays of objects
var array1 = [
{id: 1, name:'fruit', rating:5},
{id: 4, name:'vegetable', rating: 3},
{id: 8, name:'meat', rating:1}
];
var array2 = [
{alimentId: 1, quantity: 2},
{alimentId: 4, quantity: 2},
{alimentId: 8, quantity: 4}
]
and I want to get a new the array1 such that
var array = [
{id: 1, name:'fruit'},
{id: 4, name:'vegetable'},
]
which has only the elements with quantity 2 matching the alimentId with the id.
I'm always getting confused with arrays and objects manipulations.. Please help
I believe the following code will solve your problem:
const func = (arr1, arr2) => {
return arr1.filter(obj => {
const objToCheck = arr2.filter(element => element.alimentId === obj.id);
return objToCheck[0].quantity === 2;
});
};
You also can send the wanted value(2) and the key name(quantity) as params.
var array1 = [
{id: 1, name:'fruit', rating:5},
{id: 4, name:'vegetable', rating: 3},
{id: 8, name:'meat', rating:1}
];
var array2 = [
{alimentId: 1, quantity: 2},
{alimentId: 4, quantity: 2},
{alimentId: 8, quantity: 4}
]
function filter(array1, array2) {
return array1
.filter(it => array2 // filter array1 by array2
.filter(it => it.quantity === 2) // filter your array2 by field quantity = 2
.map(it => it.alimentId) // pull out array of alimentId
.includes(it.id) // check array2.alimentId includes array1.id
)
}
console.log(filter(array1, array2))
use this function
const common_elements = (arr1, arr2, quantity) => {
let res = []
arr1.forEach(el1 => {
arr2.forEach(el2 => {
if(el1.id === el2.alimentId && el2.quantity === quantity) {
res.push(el1)
}
});
});
return res
}
You can do a reduce:
var array3 = array1.reduce((acc ,val ,index) => {
if (val.id=array2[index].alimentId) {
acc =[...acc, {id: val.id, name: val.name}]
}
return acc;
},[]);
var array1 = [
{id: 1, name:'fruit', rating:5},
{id: 4, name:'vegetable', rating: 3},
{id: 8, name:'meat', rating:1}
];
var array2 = [
{alimentId: 1, quantity: 2},
{alimentId: 4, quantity: 2},
{alimentId: 8, quantity: 4}
]
const commonArray = array2.filter(item => item.quantity === 2 && array1.find(el => el.id===item.alimentId));
console.log(commonArray)
This question already has answers here:
How can I group an array of objects by key?
(32 answers)
Closed 2 years ago.
I am retrieving data from a football (soccer) API. The specific data I need is an array of objects (306 objects). Every object has a property called matchday with a numeric value. I want to group all the objects that share the same property and store them in an array. What I need in the end is an array of array of objects.
Example array of objects:
[
{id: 264796, matchday: 1, …},
{id: 264797, matchday: 1, …},
{id: 264798, matchday: 2, …},
{id: 264800, matchday: 2, …},
]
What I want looks like this:
[
[{id: 264796, matchday: 1, …},{id: 264797, matchday: 1, …}],
[{id: 264798, matchday: 2, …},{id: 264800, matchday: 2, …}],
]
You can use .reduce() with Object.values() to get the desired output:
const data = [
{id: 264796, matchday: 1}, {id: 264797, matchday: 1},
{id: 264798, matchday: 2}, {id: 264800, matchday: 2}
];
const result = Object.values(
data.reduce((r, c) => {
r[c.matchday] = r[c.matchday] || [];
r[c.matchday].push(c);
return r;
}, {})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
we can use reduce
const arr = [
{id: 264796, matchday: 1},
{id: 264797, matchday: 1},
{id: 264798, matchday: 2},
{id: 264800, matchday: 2},
]
const result = arr.reduce((acc, item) => {
if (!acc.find(accSubArr => accSubArr.find(accSubArrItem => accSubArrItem.matchday === item.matchday))) {
acc.push(arr.filter(arrItem => arrItem.matchday === item.matchday))
}
return acc;
}, [])
console.log(result)
You can try this:
const data = [{
id: 264796,
matchday: 1
},
{
id: 264797,
matchday: 1
},
{
id: 264798,
matchday: 2
},
{
id: 264800,
matchday: 2
},
]
const group = data
.map(d => d.matchday)
.filter((v, i, c) => c.indexOf(v) === i)
.map(i => data.filter(d => d.matchday === i))
console.log(group)
To add to the existing answers, here's another way making use of Map with a predicate to determine the group-by value:
const groupBy = predicate => items =>
Array.from(items.reduce((agg, next) => {
const key = predicate(next);
return agg.set(key, [].concat(agg.get(key) || []).concat(next));
}, new Map()).values());
const data = [
{name: 'A', key: 1},
{name: 'B', key: 1},
{name: 'C', key: 2},
{name: 'D', key: 2},
{name: 'E', key: 3}
];
const grouped = groupBy(x => x.key)(data);
For the fun of it, here's a recursive version of groupBy:
const groupBy = predicate => function group([next, ...items], grouped = new Map()) {
if (!next) {
return Array.from(grouped.values())
}
const key = predicate(next);
return group(items, grouped.set(key, [...(grouped.get(key) || []), next]));
}
And what the heck, here's a more imperative approach to add to the mix:
const groupBy = predicate => items => {
const cache = {};
for(item of items) {
const key = predicate(item);
cache[key] = [].concat(cache[key]).concat(item).filter(x => x)
}
return Object.values(cache);
}
I've created this list by grouping elements from another list (with d3.nest)
array = [ {key: "6S", values: [{Id: "1234a", ECTS: 3},
{Id: "1234b", ECTS: 3}]},
{key: "7S", values: [{Id: "1534a", ECTS: 5},
{Id: "154b", ECTS: 4},]} ]
From this list I want to create something like this:
array = [{key: "6S", values: { 3: [{Id: "1234a"}, {Id: "1234b"}]}},
{key: "7S", values: { 5: [{Id: "1534a"}], 4: [{Id:"1534a"}]}}]
Actually I want to group the data for each key (6S, 7S) by ECTS.
I've tried with _.groupBy.... but is not working. The problem is that the elements that I want to group are objects, already grouped once.
Any idea about how I could group the items?
You can try following
var array = [ {key: "6S", values: [{Id: "1234a", ECTS: 3}, {Id: "1234b", ECTS: 3}]}, {key: "7S", values: [{Id: "1534a", ECTS: 5}, {Id: "154b", ECTS: 4},]} ];
array.forEach((obj) => {
var values = {};
// Iterate over array and create the updated value
obj.values.forEach((item) => {
values[item.ECTS] = values[item.ECTS] || [];
values[item.ECTS].push({"Id" : item.Id});
});
// Set the updated value in object
obj.values = values;
});
console.log(array);
var array = [{
key: "6S",
values: [{
Id: "1234a",
ECTS: 3
},
{
Id: "1234b",
ECTS: 3
}
]
},
{
key: "7S",
values: [{
Id: "1534a",
ECTS: 5
},
{
Id: "154b",
ECTS: 4
},
]
}
]
array = array.map(function(v1) {
var updatedVal = v1.values.reduce(function(obj, v2) {
obj[v2.ECTS] = obj[v2.ECTS] || [];
obj[v2.ECTS].push({
Id: v2.Id
});
return obj;
}, {});
v1.values = updatedVal;
return v1;
});
console.log(array);
Is it possible to concat two arrays with objects and let the second array overwrite the first array where they have the same id:
// array 1
[
{id: 1, name: "foo"},
{id: 2, name: "bar"},
{id: 3, name: "baz"}
]
// array 2:
[
{id: 1, name: "newFoo"},
{id: 4, name: "y"},
{id: 5, name: "z"}
]
// out:
[
{id: 1, name: "newFoo"}, // overwriten by array 2
{id: 2, name: "bar"}, // not changed (from array 1)
{id: 3, name: "baz"}, // not changed (from array 1)
{id: 4, name: "y"}, // added (from array 2)
{id: 5, name: "z"} // added (from array 2)
]
If it is possible I would like to do this without the use of third party libraries
var a = [
{id: 1, name: "foo"},
{id: 2, name: "bar"},
{id: 3, name: "baz"}
];
var b = [
{id: 1, name: "fooboo"},
{id: 4, name: "bar"},
{id: 5, name: "baz"}
];
/* iterate through each of b, if match found in a, extend with that of a. else push into b ...*/
b.forEach(m => {
var item = a.find(n => n.id === m.id);
if(item) { return Object.assign(item, m); }
a.push(m);
});
console.log(a);
You can do
let arr1 = [
{id: 1, name: "foo"},
{id: 2, name: "bar"},
{id: 3, name: "baz"}
]
let arr2 = [
{id: 1, name: "newFoo"},
{id: 4, name: "y"},
{id: 5, name: "z"}
]
let result = arr1.concat(arr2).reduce((a, b) => {
a[b.id] = b.name;
return a;
},{})
result = Object.keys(result).map(e => {
return {id : e, name : result[e]};
});
console.log(result);
Explanation
I am using the property of objects that they don't keep duplicate keys, so for an array concated together, I reduce it to an object with id as it's key and name as its value, hence overriding all duplicates. In the next step I converted this back into an array.
Check you my solution. There is no "rewrite", i just use a second array as base and don't write value if it has same id.
let a = [
{id: 1, name: "foo"},
{id: 2, name: "bar"},
{id: 3, name: "baz"}
];
let b = [
{id: 1, name: "newFoo"},
{id: 4, name: "y"},
{id: 5, name: "z"}
];
let duplicateId;
a.forEach(aitem => {
duplicateId = false;
b.forEach(bitem => {
if (aitem.id === bitem.id)
duplicateId = true;
});
if (!duplicateId)
b.push(aitem);
});
console.log(b);
Maybe you can use Object.assign and Object.entries to achieve, lets say:
const arr1 = [
{id: 1, name: "foo"},
{id: 2, name: "bar"},
{id: 3, name: "baz"}
]
const arr2 = [
{id: 1, name: "newFoo"},
{id: 4, name: "y"},
{id: 5, name: "z"}
]
const obj3 = Object.entries(Object.assign({}, ...arr1, arr2))
.map(([prop, value]) => ({[prop]:value}));
Example:
https://jsfiddle.net/0f75vLka/
Another option would be to convert arrays to map with id as key then merge the objects and then convert it back to array.
var arr1 = [
{id: 1, name: "foo"},
{id: 2, name: "bar"},
{id: 3, name: "baz"}
];
var arr2 = [
{id: 1, name: "newFoo"},
{id: 4, name: "y"},
{id: 5, name: "z"}
];
function arr2map(arr) {
var map = {};
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
map[item.id] = item;
}
return map;
}
function map2arr(map) {
var arr = [];
for (var i in map) {
arr.push(map[i]);
}
return arr;
}
var arr1m = arr2map(arr1);
var arr2m = arr2map(arr2);
var arr3m = map2arr( Object.assign({}, arr1m, arr2m) );
//output
alert(JSON.stringify(arr3m));