Convert array of objects in an array of array of objects [duplicate] - javascript

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);
}

Related

Filtering two arrays with .filter [duplicate]

This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Closed 2 years ago.
I'm trying to get information, a have all the data that i get from Database and now I need to do something that should be simple (but not for a novice like me xd), I'm trying to do the next filter in JS
const array1 = [{id: 'a'}, {id: '8'}, {id: 'c'}, {id: 'a'}];
const array2 = [{id: 'a'}, {id: 'c'}];
console.log(array1.filter(id => id.id == array2.id))
It doesn't returns me nothing, and I don't understand why, also I try to use:
console.log(array1.filter(id => id.id == array2.id))
My result is all the values from array1, I mean I only want the elements that have the same Id that array2 from array1, in other words, I want that its returns me 2 objects with Id = a and one with id = c
Use Array.some() inside Array.filter() callback method.
const array1 = [{id: 'a'}, {id: '8'}, {id: 'c'}, {id: 'a'}];
const array2 = [{id: 'a'}, {id: 'c'}];
const output = array1.filter(item1 => array2.some(item2 => item2.id === item1.id))
console.log(output);
This will return three objects, because in array1 there are two objects with id: a and one with id: c.
const array1 = [{id: 'a'}, {id: '8'}, {id: 'c'}, {id: 'a'}];
const array2 = [{id: 'a'}, {id: 'c'}];
let res = array1.filter(obj1 => array2.find(obj2 => obj1.id === obj2.id))
console.log(res)
You can filter out duplicate objects with Array.reduce():
const array1 = [{id: 'a'}, {id: '8'}, {id: 'c'}, {id: 'a'}];
const array2 = [{id: 'a'}, {id: 'c'}];
let res = array1.filter(obj1 => {
return array2.find(obj2 => obj1.id === obj2.id)
})
.reduce((acc,cur) => {
if(!acc.find(obj => obj.id === cur.id)){
acc.push(cur)
}
return acc
},[])
console.log(res)
You could take a Set and filter the array.
This approach takes a single loop for building the set and another for filtering.
const
array1 = [{ id: 'a' }, { id: '8' }, { id: 'c' }, { id: 'a' }],
array2 = [{ id: 'a' }, { id: 'c' }],
set2 = new Set(array2.map(({ id }) => id)),
result = array1.filter(({ id }) => set2.has(id));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can to use .some to check if array2 has an element with a given id:
const array1 = [{id: 'a'}, {id: '8'}, {id: 'c'}, {id: 'a'}];
const array2 = [{id: 'a'}, {id: 'c'}];
const res = array1.filter(({id}) => array2.some(e => e.id===id));
console.log(res);
A better way would be using a Set:
const array1 = [{id: 'a'}, {id: '8'}, {id: 'c'}, {id: 'a'}];
const array2 = [{id: 'a'}, {id: 'c'}];
const idsInArray2 = new Set(array2.map(({id}) => id));
const res = array1.filter(({id}) => idsInArray2.has(id));
console.log(res);

display entire array after moving values of it to another array

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}])
);

how get common elements of 2 different arrays and return an object containing the common elements

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)

Filter and create a new array [duplicate]

This question already has answers here:
Using array map to filter results with if conditional
(5 answers)
Map and filter an array at the same time
(16 answers)
Closed 3 years ago.
I have an object as shown below:
var obj = [
{id: 1, name: 'AD', key: 10},
{id: 2, name: 'AD', key: 20},
{id: 3, name: 'BD', key: 30},
{id: 4, name: 'CD', key: 40}
];
I want to filter and create a new array which satisfies any condition. For eg: filter which have name as 'AD' and create a new array of key as:
[10, 20]
Tried .map
obj.map(ele => {
return ele.name === 'AD' ? ele.key : null;
}); //it adds even nulls in the result array as [10, 20, null, null]
Tried .filter:
obj.filter(ele => {
return ele.name === 'AD' ? ele.key : null;
});
Result: [{id: 1, name: "AD", key: 10}, {id: 2, name: "AD", key: 20}] //gives array of objects, not what I'm expecting.
Thanks in advance
First filter the array and then map to get the value:
obj.filter(e => e.name === 'AD').map(e => e.key)
Another option is flatmap (check browser compatibility here)
obj.flatMap(e => e.name === 'AD' ? [e.key] : [])
First of all obj is an array in your code.
Now the solution is simple you filter first and then map like this:
obj.filter(item => item.name === 'AD').map(item => item.key);
You can use reduce():
var obj = [{id: 1, name: 'AD', key: 10},{id: 2, name: 'AD', key: 20},{id: 3, name: 'BD', key: 30},{id: 4, name: 'CD', key: 40}];
var result = obj.reduce((acc, cur) => {
if (cur.name == "AD") acc.push(cur.key)
return acc;
}, []);
console.log(result);
var obj = [
{id: 1, name: 'AD', key: 10},
{id: 2, name: 'AD', key: 20},
{id: 3, name: 'BD', key: 30},
{id: 4, name: 'CD', key: 40}
];
function specialFilter(filt) {
return obj.filter(el => el.name === filt).map(el => el.key)
}
console.log(specialFilter("AD"))

Grouping elements in javascript

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);

Categories