I have an array of objects, I need to group them by the same value, I need to group them by a multidimensional array
const source = [
{name: 'A', age: 23, id: 0},
{name: 'A', age: 23, id: 1},
{name: 'B', age: 15, id: 34},
{name: 'B', age: 15, id: 45},
{name: 'B', age: 15, id: 32},
{name: 'C', age: 15, id: 32},
];
[
Like this structure, all the same objects should be grouped by array inside an array.
[
{name: 'A', age: 23, id: 0},
{name: 'A', age: 23, id: 1}
],
[
{name: 'B', age: 15, id: 34},
{name: 'B', age: 15, id: 45},
{name: 'B', age: 15, id: 32}
],
[
{name: 'C', age: 15, id: 32},
]
]
I have tried like this but no luck.
const result = source.reduce((accumulator, item) => {
if (accumulator && accumulator.length) {
const found = accumulator.find(group => {
return group && group.length
? group.find(_transaction =>
// check the same object
return false
)
: false;
});
if (found) {
console.log(found);
}
} else {
accumulator.push([item]);
}
return accumulator;
}, []);
Create an object indexed by the name property, whose values are arrays containing the source items, then take the object's values:
const source = [
{name: 'A', age: 23, id: 0},
{name: 'A', age: 23, id: 1},
{name: 'B', age: 15, id: 34},
{name: 'B', age: 15, id: 45},
{name: 'B', age: 15, id: 32},
{name: 'C', age: 15, id: 32},
];
const sourceItemsByName = {};
for (const obj of source) {
if (!sourceItemsByName[obj.name]) {
sourceItemsByName[obj.name] = [];
}
sourceItemsByName[obj.name].push(obj);
}
const output = Object.values(sourceItemsByName);
console.log(output);
You can reduce the array to a Map, using the name and age combination as the key. Then spread the Map.values() iterator back to an array:
const source = [{ name: 'A', age: 23, id: 0 }, { name: 'A', age: 23, id: 1 }, { name: 'B', age: 15, id: 34 }, { name: 'B', age: 15, id: 45 }, { name: 'B', age: 15, id: 32 }, { name: 'C', age: 15, id: 32 }];
const result = [... // spread the values iterator to an array
source.reduce((r, o) => {
const key = `${o.name}---${o.age}`; // generate a key with name and age
if(!r.has(key)) r.set(key, []); // add a new entry for key if it's not in the Map
r.get(key).push(o); // push the current object to the keys's entry
return r;
}, new Map())
.values() // get the Maps values iterator
];
console.log(result);
I think the following code is easier to understand. Hope, it will help you. Thanks.
UPDATED: As you need mentioned in a comment that you need name and age property as your key value.
const source = [
{name: 'A', age: 23, id: 0},
{name: 'A', age: 23, id: 1},
{name: 'B', age: 15, id: 34},
{name: 'B', age: 15, id: 45},
{name: 'B', age: 15, id: 32},
{name: 'C', age: 15, id: 32},
];
var hashObject = {}
source.forEach(function(elem) {
var key = elem.name + elem.age;
if (hashObject[key]) {
hashObject[key].push(elem);
} else {
hashObject[key] = [elem];
}
});
var desiredArray = Object.values(hashObject);
console.log(desiredArray);
You could find the group array and if found add the object or add a new group to the result set.
const
source = [{ name: 'A', age: 23, id: 0 }, { name: 'A', age: 23, id: 1 }, { name: 'B', age: 15, id: 34 }, { name: 'B', age: 15, id: 45 }, { name: 'B', age: 15, id: 32 }, { name: 'C', age: 15, id: 32 }],
groups = ['name', 'age'],
grouped = source.reduce((r, o) => {
var temp = r.find(([q]) => groups.every(k => o[k] === q[k]));
if (temp) {
temp.push(o);
} else {
r.push([o]);
}
return r;
}, []);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
An approach with a Map
const
source = [{ name: 'A', age: 23, id: 0 }, { name: 'A', age: 23, id: 1 }, { name: 'B', age: 15, id: 34 }, { name: 'B', age: 15, id: 45 }, { name: 'B', age: 15, id: 32 }, { name: 'C', age: 15, id: 32 }],
groups = ['name', 'age'],
grouped = Array.from(source
.reduce(
(m, o) =>
(k => m.set(k, [...(m.get(k) || []), o]))
(groups.map(k => o[k]).join('|')),
new Map)
.values()
);
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Related
I have the data from the database and I want to push the duplicate value to each array. I attach the exact example I want.
// origin data
const data = [
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Tommy",
age: 20,
},
{
name: "Tommy",
age: 20,
},
];
//result that I want to get
arr1 = [
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
];
arr2 = [
{
name: "Tommy",
age: 20,
},
{
name: "Tommy",
age: 20,
},
];
I want to create an array based on the name in this data and push it. Can anyone help?
One way would be to use reduce together with Object.values:
const data = [
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Amy",
age: 17,
},
{
name: "Tommy",
age: 20,
},
{
name: "Tommy",
age: 20,
}
];
const result = Object.values(data.reduce((acc, cur) => {
const key = `${cur.name}:${cur.age}`;
const prev = acc[key] || [];
return {
...acc,
[key]: prev.concat(cur)
}
}, {}));
console.log(result);
Hi guys and sorry for my english. I have this array of objects and I need to get an input like:
{name: Karen, age: 12} -> Karen-12.
How can I do it?
This is the exercise:
function nicknameMap(p) {
}
const p = [
{ name: 'ninny', age: 19},
{ name: 'albert', age: 20},
{ name: 'daniel', age: 60},
{ name: 'bob', age: 20},
{ name: 'wilfred', age: 40},
{ name: 'rob', age: 22},
{ name: 'gary', age: 9},
{ name: 'robin', age: 19},
{ name: 'carl', age: 43 },
{ name: 'v', age: 82 }
];
const nicknames = nicknameMap(p);
console.log(p);
console.log(nicknames);```
Use the .map() array method as follows:
function nicknameMap(p) {
return p.map(({name,age}) => `${name}-${age}`);
}
//output
//[
// "ninny-19",
// "albert-20",
// "daniel-60",
// "bob-20",
// .....
//]
function nicknameMap(p) {
return p.map(({name,age}) => `${name}-${age}`);
}
const p = [
{ name: 'ninny', age: 19},
{ name: 'albert', age: 20},
{ name: 'daniel', age: 60},
{ name: 'bob', age: 20},
{ name: 'wilfred', age: 40},
{ name: 'rob', age: 22},
{ name: 'gary', age: 9},
{ name: 'robin', age: 19},
{ name: 'carl', age: 43 },
{ name: 'v', age: 82 }
];
const nicknames = nicknameMap(p);
console.log(p);
console.log(nicknames);
function nicknameMap(p) {
let result = Array();
p.forEach((n) => {
result.push(`${n.name}-${n.age}`);
});
return result;
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
It's best to learn by yourself, but I'm assuming you've had a crack at it and are asking because you have run out of options.
EDIT: amlxv solution is a more "Javascript" way of doing it, and is technically more correct than mine.
Below is a solution to your problem.
function nicknameMap(p) {
let arr = [];
for(let i = 0; i<p.length; i++){
arr.push(p[i].name + "-" + p[i].age);
}
return arr;
}
const p = [
{ name: 'ninny', age: 19},
{ name: 'albert', age: 20},
{ name: 'daniel', age: 60},
{ name: 'bob', age: 20},
{ name: 'wilfred', age: 40},
{ name: 'rob', age: 22},
{ name: 'gary', age: 9},
{ name: 'robin', age: 19},
{ name: 'carl', age: 43 },
{ name: 'v', age: 82 }
];
const nicknames = nicknameMap(p);
console.log(p);
console.log(nicknames);
I have an array of json elements. and I want to filter the array based on the specific values. below is the array.
var arr = [
{name: bobby, id: 1, age: 23},
{name: charls, id: 2, age: 28},
{name: indi, id: 3, age: 23},
{name: charlie, id: 4, age: 25}]
from the above array I want to filter only staff whose names are bobby && indi. I have tried below code.
var filteredArray;
for (var i =0 ; i < arr.length; i++){
if(arr[i].name === 'bobby' || arr[i].name === 'indi'){
filteredArray.push(arr[i]);
}
}
but through the above code, I need to mention OR(||) conditions too many times and these number of names can change like 1 time I want only staff with Bobby name and other time I want Bobby, Indi and Charlie. is there a way to make it dynamic. if yes, please let me know. Thanks in advance.
You can store names that needs to be filters in an array and then check if name exists in array or not
eg.
var arr = [
{name: "bobby", id: 1, age: 23},
{name: "charls", id: 2, age: 28},
{name: "indi", id: 3, age: 23},
{name: "charlie", id: 4, age: 25}
]
const names = ["bobby", "indi"];
const filtered = arr.filter((item)=>{
return names.includes(item.name)
});
console.log(filtered)
For older(eg. IE11) browsers -
var arr = [
{name: "bobby", id: 1, age: 23},
{name: "charls", id: 2, age: 28},
{name: "indi", id: 3, age: 23},
{name: "charlie", id: 4, age: 25}
]
const names = ["bobby", "indi"];
const filtered = [];
for(var i =0; i<arr.length - 1; i++){
if(names.indexOf(arr[i].name) > -1){
filtered.push(arr[i])
}
}
console.log(filtered)
You can use Array.includes() to filter items as followings:
var arr = [
{name: 'bobby', id: 1, age: 23},
{name: 'charls', id: 2, age: 28},
{name: 'indi', id: 3, age: 23},
{name: 'charlie', id: 4, age: 25}
]
const keywords = ['bobby', 'indi'] // You can add keywords to be filtered to this array to make it dynamic
const filtered = arr.filter(item => keywords.includes(item.name))
console.log(filtered)
You could create an array of names you want to filter and then:
if you want to stick to pre-ES6 coding:
var arr = [{
name: 'bobby',
id: 1,
age: 23
},
{
name: 'charls',
id: 2,
age: 28
},
{
name: 'indi',
id: 3,
age: 23
},
{
name: 'charlie',
id: 4,
age: 25
}
];
var names = ['bobby', 'indi'];
var filteredArray = [];
for (var i = 0; i < arr.length; i++) {
if (names.indexOf(arr[i].name) > -1) filteredArray.push(arr[i]);
}
console.log(filteredArray);
or, if you are willing to switch to ES6+ coding:
const arr = [{
name: 'bobby',
id: 1,
age: 23
},
{
name: 'charls',
id: 2,
age: 28
},
{
name: 'indi',
id: 3,
age: 23
},
{
name: 'charlie',
id: 4,
age: 25
}
];
const names = ['bobby', 'indi'];
const filteredArray = arr.filter(item => names.includes(item.name));
console.log(filteredArray);
I've 2 arrays with partial information and I wish to merge those arrays with all the information into one array.
Array 1 :
const arr1 = [
{
name: 'Rohan',
surname: 'Mehra',
age: '15',
date: "2021-01-19",
location: 'Goa'
},
{
name: 'Aman',
surname: 'Kohli',
age: '14',
date: "2021-01-19",
location: 'Kolkata'
},
{
name: 'Sam',
surname: 'Sharma',
age: '16',
date: "2021-01-21",
location: 'Mumbai'
}
]
Array 2 :
const arr2 = [
{
rollNo: 1,
marks: 100,
name: 'Rohan',
date: "2021-01-19",
},
{
rollNo: 2,
marks: 90,
surname: 'Kohli',
date: "2021-01-19",
},
{
rollNo: 3,
marks: 70,
date: "2021-01-21",
ExamCenter: {
place: 'Mumbai'
}
}
]
I want to get a final array with the properties from both arrays. The Object keys sometimes change and I wanted to match the key with the other common key and merge them. But I am not able to proceed with the solution. Here is the result array I wish to get.
const final = [
{
name: 'Rohan',
surname: 'Mehra',
age: '15',
date: "2021-01-19",
location: 'Goa',
rollNo: 1,
marks: 100,
},
{
name: 'Aman',
surname: 'Kohli',
age: '14',
date: "2021-01-19",
location: 'Kolkata',
rollNo: 2,
marks: 90,
},
{
name: 'Sam',
surname: 'Sharma',
age: '16',
date: "2021-01-21",
location: 'Mumbai',
rollNo: 3,
marks: 70,
}
]
I'm trying with nested map loops but not able to proceed
const final = arr1.map((item,index) => {
arr2.map((innerItem, i) => {
if(item[Object.keys(innerItem)][index] === innerItem[Object.keys(innerItem)][0]){
console.log(item);
}
})
})
There is a mistake in your arr2. The surname for 2nd item should be kohli instead of kolhi. Anyway, You can do the following to merge two array based on dynamic matching attribute. What we are doing here is,
For each item of arr1 we are finding the keys using Object.keys method and checking which object from arr2 has maximum matching object with the item of arr1. Then we merge the two item together.
arr1 = [
{
name: 'Rohan',
surname: 'Mehra',
age: '15',
date: "2021-01-19",
location: 'Goa'
},
{
name: 'Aman',
surname: 'Kohli',
age: '14',
date: "2021-01-19",
location: 'Kolkata'
},
{
name: 'Sam',
surname: 'Sharma',
age: '16',
date: "2021-01-21",
location: 'Mumbai'
}
]
arr2 = [
{
rollNo: 1,
marks: 100,
name: 'Rohan',
date: "2021-01-19",
},
{
rollNo: 2,
marks: 90,
surname: 'Kohli',
date: "2021-01-19",
},
{
rollNo: 3,
marks: 70,
date: "2021-01-21",
ExamCenter: {
place: 'Mumbai'
}
}
]
res = arr1.map(item => {
keys1 = Object.keys(item);
let max = 0;
const temp = arr2.reduce((prev, item2) => {
maxTemp = keys1.filter(key => item[key] === item2[key]).length;
if(maxTemp > max) {
max = maxTemp;
prev = item2;
}
return prev;
}, {})
if(temp) {
return {...item, ...temp}
}
});
console.log(res);
You can do something like this to merge two arrays.
const arr1 = [
{
name: 'Rohan',
surname: 'Mehra',
age: '15',
date: "2021-01-19",
location: 'Goa'
},
{
name: 'Aman',
surname: 'Kohli',
age: '14',
date: "2021-01-19",
location: 'Kolkata'
},
{
name: 'Sam',
surname: 'Sharma',
age: '16',
date: "2021-01-21",
location: 'Mumbai'
}
]
const arr2 = [
{
rollNo: 1,
marks: 100,
name: 'Rohan',
date: "2021-01-19",
},
{
rollNo: 2,
marks: 90,
surname: 'Kolhi',
date: "2021-01-19",
},
{
rollNo: 3,
marks: 70,
date: "2021-01-21",
ExamCenter: {
place: 'Mumbai'
}
}
]
const newArray = [];
arr2.forEach((item) => {
const array1Item = arr1.find(({ date }) => date === item.date);
if (array1Item) {
newArray.push({
...item,
...array1Item,
})
}
})
console.log(newArray);
This may help you
const arr3 = arr1.map((value, index) => {
return Object.assign(value, arr2[index])
})
How do I get 2 matching id between 2 array object using javascript?
// Array 1
const array1 = [
{id: 1, name: 'milla'},
{id: 2, name: 'alice'}
]
// Array 2
const array2 = [
{id: 3, name: 'bobba', height: '170cm', age: 22},
{id: 2, name: 'alice', height: '169cm', age: 21},
{id: 1, name: 'milla', height: '171cm', age: 24},
{id: 4, name: 'ricky', height: '168cm', age: 32},
]
the expected output is to returned array of object of Array2 that mached with id's on array1
// expected result
[
{id: 2, name: 'alice', height: '169cm', age: 21},
{id: 1, name: 'milla', height: '171cm', age: 24},
]
You could filter and look if the same id exists.
const
array1 = [{ id: 1, name: 'milla' }, { id: 2, name: 'alice' }],
array2 = [{ id: 3, name: 'bobba', height: '170cm', age: 22 }, { id: 2, name: 'alice', height: '169cm', age: 21 }, { id: 1, name: 'milla', height: '171cm', age: 24 }, { id: 4, name: 'ricky', height: '168cm', age: 32 }],
hash = array1.reduce((r, { id }) => (r[id] = true, r), {}),
filtered = array2.filter(({ id }) => hash[id]);
console.log(filtered);
The most efficient way to do this is to generate a map of the IDs in array1 and then filter array2 against those IDs, like so:
let array1 = [{ id: 1, name: 'milla' }, { id: 2, name: 'alice' }];
let array2 = [{ id: 3, name: 'bobba', height: '170cm', age: 22 }, { id: 2, name: 'alice', height: '169cm', age: 21 }, { id: 1, name: 'milla', height: '171cm', age: 24 }, { id: 4, name: 'ricky', height: '168cm', age: 32 }];
let idMap = array1.reduce((res, curr) => (res[curr.id] = true, res), {});
let filtered = array2.filter((item) => idMap[item.id]);
console.log(filtered)
Honestly, this is basic JS, but anyway, here's the solution:
const array1 = [
{id: 1, name: 'milla'},
{id: 2, name: 'alice'}
]
// Array 2
const array2 = [
{id: 3, name: 'bobba', height: '170cm', age: 22},
{id: 2, name: 'alice', height: '169cm', age: 21},
{id: 1, name: 'milla', height: '171cm', age: 24},
{id: 4, name: 'ricky', height: '168cm', age: 32},
]
const map = array1.reduce((a, c) => ({ ...a, [c.id]: true }), {});
const array3 = array2.filter(item => map[item.id]);
console.log(array3);