This question already has answers here:
Merge two array of objects based on a key
(23 answers)
Closed 1 year ago.
I have a small exercise, to merge three arrays into one array by matching ID's, I'd like to add the likes and comments array into the posts array how would I go about this?
const posts =
[ { _id: 1
, message: 'this is post one'
, likes: [ { id: 1111 } , { id: 2222 } ]
, comments: [ { id: 3333 } , { id: 4444 } ]
}
]
const comments =
[ { id: 3333, message: 'this is comment 1' }
, { id: 4444, message: 'this is comment 2' }
]
const likes =
[ { id: 1111, user: 'Peter' }
, { id: 2222, user: 'John' }
]
expected output:
newArray =
[ { _id: 1
, message: 'this is post one'
, likes:
[ { id: 1111, user: 'Peter'}
, { id: 2222, user: 'John'} ]
, comments:
[ { id: 3333, message: 'this is comment 1'}
, { id: 4444, message: 'this is comment 2'}
] } ]
Here is a similar approach I've used when working with two arrays:
const
arr1 = [{ groupId: "Category", options: [{ name: "cookies", id: 1111 }, { name: "tv", id: 2222 }] }, { groupId: "Brand", options: [{ name: "random", id: 3333 }] }, { groupId: "Price", options: [{ name: "random2", id: 4444 }] }],
arr2 = [{ id: 1111, url: "/test", other: 'other-prop' }, { id: 2222, url: "/test1" }, { id: 3333, url: "/test2" }],
mergeById = (arr1, arr2) =>
arr1.map(({ options, ...rest }) => (
{
...rest,
options: options.map(option => (
{
...option,
...arr2.find(_option => _option.id === option.id)
}
))
}
));
const merged = mergeById(arr1, arr2);
console.log(JSON.stringify(merged, null, 2));
const newPosts = posts.map(post => ({
...post,
likes: likes.filter(like => post.likes.map(like => like.id).includes(like.id)),
comments: comments.filter(comment => post.comments.map(comment => comment.id).includes(comment.id)),
}))
console.log(newPosts)
Related
This is my array, I'm working on react app
const categoryObj = [
{
id: "463e989a-c4f2-4616-85c5-0cb610c5fff0",
name: "Women",
subCategory: [
{
id: "91ba7308-b68e-4d0c-85d8-0cc8272c6bc8",
name: "All",
icon: "AllIcon"
},
{
id: "0e0712c5-0b5a-4d4e-acf5-3d7faf2caa2a",
name: "Clothes",
icon: "ClothesIcon",
sections: [
{
id: "9b7a7a58-04a1-4aba-ba68-0e6b1390021e",
name: "All",
href: "Women/Clothes/All".split(' ').join('-').trim().toLowerCase()
}
]
}
]
}
]
how can I access "women" in this array ? (I have many items like "women" this is just a sample of a large array. if you can suggest a mapping method it's better.)
You can map through it to get the name value in this way:
categoryObj.map((category) => category.name)
const categoryObj = [
{
id: "463e989a-c4f2-4616-85c5-0cb610c5fff0",
name: "Women",
subCategory: [
{
id: "91ba7308-b68e-4d0c-85d8-0cc8272c6bc8",
name: "All",
icon: "AllIcon"
},
{
id: "0e0712c5-0b5a-4d4e-acf5-3d7faf2caa2a",
name: "Clothes",
icon: "ClothesIcon",
sections: [
{
id: "9b7a7a58-04a1-4aba-ba68-0e6b1390021e",
name: "All",
href: "Women/Clothes/All".split(' ').join('-').trim().toLowerCase()
}
]
}
]
},
{
id: "463e989a-c4f2-4616-85c5-0cb610c5fff0",
name: "Men",
subCategory: [
{
id: "91ba7308-b68e-4d0c-85d8-0cc8272c6bc8",
name: "All",
icon: "AllIcon"
},
{
id: "0e0712c5-0b5a-4d4e-acf5-3d7faf2caa2a",
name: "Clothes",
icon: "ClothesIcon",
sections: [
{
id: "9b7a7a58-04a1-4aba-ba68-0e6b1390021e",
name: "All",
href: "Women/Clothes/All".split(' ').join('-').trim().toLowerCase()
}
]
}
]
},
{
id: "463e989a-c4f2-4616-85c5-0cb610c5fff0",
name: "Children",
subCategory: [
{
id: "91ba7308-b68e-4d0c-85d8-0cc8272c6bc8",
name: "All",
icon: "AllIcon"
},
{
id: "0e0712c5-0b5a-4d4e-acf5-3d7faf2caa2a",
name: "Clothes",
icon: "ClothesIcon",
sections: [
{
id: "9b7a7a58-04a1-4aba-ba68-0e6b1390021e",
name: "All",
href: "Women/Clothes/All".split(' ').join('-').trim().toLowerCase()
}
]
}
]
}
]
const result = categoryObj.filter(obj => obj.name === 'Women')
console.log('multi objects :', result)
// if unique with name
const resultUnique = categoryObj.find(obj => obj.name === 'Women')
console.log('unique object :', resultUnique)
This object contains an object and have another variations as sub. If you want to access first name,
categoryObj.map((it) => {
//You can handle it like this
console.log(it.name)
})
But if you want all name of all subCategory,
categoryObj[0].subCategory.map((cat) => {
//You can handle it like this
console.log(cat.name)
})
You have same object-type in and out.
const res = categoryObj.filter(item=>item.name === 'Women');
i have two arrays.
const department = [
{ id: '1', name: 'department1' },
{ id: '2', name: 'department2' },
];
const models = [
{
id: '23',
name: 'model1',
departments: [{ id: '1', name: 'department1' }],
},
{
id: '54',
name: 'model2',
departments: [
{ id: '1', name: 'department1' },
{ id: '2', name: 'department2' },
],
},
];
i need to render accordions with department names and accordion details with matching models names. My question is how to filter those arrays to get models
We can map through the departments array, and add a models property that equals the models array, but filtered only to the ones that contain a matching department id.
const departments = [
{ id: "1", name: "department1" },
{ id: "2", name: "department2" },
];
const models = [
{
id: "23",
name: "model1",
departments: [{ id: "1", name: "department1" }],
},
{
id: "54",
name: "model2",
departments: [
{ id: "1", name: "department1" },
{ id: "2", name: "department2" },
],
},
];
const getDepartmentsWithModels = () => {
return departments.map((department) => {
return {
...department,
models: models.filter((model) => {
const modelDepartmentIds = model.departments.map(({ id }) => id);
return modelDepartmentIds.includes(department.id);
}),
};
});
};
console.log(getDepartmentsWithModels());
// [ { id: '1', name: 'department1', models: [ [Object], [Object] ] },
// { id: '2', name: 'department2', models: [ [Object] ] } ]```
I've built some code, which iterates over the departments. For each department it iterates the models and for each model it checks if the department is within the model departments.
const department =
[
{ id: '1', name: 'department1' },
{ id: '2', name: 'department2' }
]
const models =
[
{
id: '23',
name: 'model1',
departments: [{ id: '1', name: 'department1' }]
},
{
id: '54',
name: 'model2',
departments: [{ id: '1', name: 'department1' },{ id: '2', name: 'department2' }]
}
]
department.forEach( dep => {
console.log(`Department: ${dep.name}`)
models.forEach(model => {
if (model.departments.find(modelDep => dep.id===modelDep.id)) {
console.log(` Model: ${model.name}`)
}
})
})
If you could change your data objects, then your code could be much smoother.
I've changed your data objects slightly by just reducing the departments in a model to be an array of department id's. This code iterates over the departments. For each department it filters the models and iterates over the filtered models to output them to the console. This is lesser code and provides much better performance.
const department =
[
{ id: '1', name: 'department1' },
{ id: '2', name: 'department2' }
]
const models =
[
{
id: '23',
name: 'model1',
departments: ['1']
},
{
id: '54',
name: 'model2',
departments: ['1', '2']
}
]
department.forEach( dep => {
console.log(`Department: ${dep.name}`)
models.filter(model => model.departments.includes(dep.id)).forEach(model => {
console.log(` Model: ${model.name}`)
})
})
There are two solutions.
Using Array.reduce() --> returns an object where the key is department name and value is an array of the names of matching models:
let data1 = models.reduce((res, curr) => {
curr.departments.forEach(dep => {
if (!res[dep.name]) {
res[dep.name] = [curr.name]
} else {
if (!res[dep.name].includes(curr.name)) {
res[dep.name].push(curr.name);
}
}
})
return res;
}, {});
Using map and filter --> returns an array of kind:
[{department: [names of the models]},...]
let data2 = department.map(dep => {
let matchingModels = models.filter(model => {
return model.departments.filter(modDep => {
return modDep.name === dep.name;
}).length > 0;
}).map(mod => {
return mod.name;
});
return {
department: dep.name,
models: matchingModels
}
});
I have two arrays of objects; districts and userCounts. I am trying to reduce districts and find userCounts inside reduce
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.find(({ _id }) => _id === curr._id)
console.log(findUser)
})
all findUser is returning undefined
districts:
[
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
userCounts:
[
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
well .filter() with .every() is better use case here
let districts = [
{
_id: "5efc41d74664920022b6c016",
name: "name1",
},
{
_id: "5efc41a44664920022b6c015",
name: "name2",
},
{
_id: "5efc2d84caa7964dcd843a7b",
name: "name3",
},
{
_id: "5efc41794664920022b6c014",
name: "name 4",
},
];
let userCounts = [
{ _id: "5efc2d84caa7964dcd843a7b", totalCount: 3 },
{ _id: "5efc41794664920022b6c014", totalCount: 1 },
];
const result = districts.filter((dist) => {
return userCounts.some(({ _id }) => _id === dist._id);
});
console.log(result);
const districs=[
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
const userCounts= [
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
let filtered=userCounts.map(item=>{
return districs.find(elemnt=>elemnt._id===item._id)
})
console.log(filtered)
here you go, you can modify it however you want.
try this if you want to use reduce and modify your array:
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.filter(({ _id }) => _id === curr._id)
return [...acc, {...curr , user:findUser.length > 0 ? findUser[0].totalCount :0 }]
},[])
const districts = [
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
const userCounts = [
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.filter(({ _id }) => _id === curr._id)
return [...acc, {...curr , user:findUser.length > 0 ? findUser[0].totalCount :0 }]
},[])
console.log(result)
Let say I have two array of objects.
var arr1= [
{
pid: [ '1967', '967' ],
},
{
pid: [ '910', '1967', '967' ],
},
{
pid: [ '967' ],
}
]
var arr2 = [
{ _id: '967', name: 'test pid' },
{ _id: '1967', name: 'test one test' },
{ _id: '910', name: 'this is test name' }
]
is there any way I can find the _id and name from array2 using the id from arr1 and replace element of arr1.pid. like below
arr1 = [
{
pid: [ { _id: '1967', name: 'test one test' }, { _id: '967', name: 'test pid' }],
},
{
pid: [ { _id: '910', name: 'this is test name' }, { _id: '1967', name: 'test one test' }, { _id: '967', name: 'test pid' } ],
},
{
pid: [ { _id: '967', name: 'test pid' } ],
}
]
so far I have done as below
for (var i = 0; i < arr1.length; i++){
var pids = arr1[i].pid
for(var j = 0; j<pids.length; j++){
var result = arr2.filter(obj => {
return obj._id === pids[j]
})
console.log(result) //can not push this into arr1['pid']
}
}
You can map it and inside that you can find the elemenet from second array:
var arr1= [ { pid: [ '1967', '967' ], }, { pid: [ '910', '1967', '967' ], }, { pid: [ '967' ], }];
var arr2 = [ { _id: '967', name: 'test pid' }, { _id: '1967', name: 'test one test' },{ _id: '910', name: 'this is test name' } ];
var result = arr1.map(k=>{
k.pid = k.pid.map(p=>arr2.find(n=>n._id==p));
return k;
});
console.log(result);
Build an object from arr2, so that easy access given key.
Use map on arr1 and update the array.
var arr1 = [
{
pid: ["1967", "967"],
},
{
pid: ["910", "1967", "967"],
},
{
pid: ["967"],
},
];
var arr2 = [
{ _id: "967", name: "test pid" },
{ _id: "1967", name: "test one test" },
{ _id: "910", name: "this is test name" },
];
// Build an object to from array
const all = arr2.reduce(
(acc, curr) => ((acc[curr._id] = { ...curr }), acc),
{}
);
const res = arr1.map(({ pid }) => ({
pid: pid.map((key) => ({ ...all[key] })),
}));
console.log(res);
I have the array as below
test_list = [
{
id: 1,
test_name: 'Test 1',
members: [
{
user_id: 3
},
{
user_id: 4
}
],
},
{
id: 2,
test_name: 'Test 2',
members: [
{
user_id: 4
},
{
user_id: 5
},
],
},
{
id: 3,
test_name: 'Test 2',
members: [
{
user_id: 8
},
{
user_id: 10
},
],
}
]
I want to filter the test for specific user_id, example if user_id = 4 I would like to have this result
{
id: 1,
...
},
{
id: 2,
...
},
I have tried with this but it only return the member
test_list.filter(function(item) {
item.members.filter(function(member) {
if(member.user_id === 4) {
return item;
}
});
})
Would anyone please help me in this case?
Check if .some of the objects in the members array have the user_id you're looking for:
test_list = [{
id: 1,
test_name: 'Test 1',
members: [{
user_id: 3
},
{
user_id: 4
}
],
},
{
id: 2,
test_name: 'Test 2',
members: [{
user_id: 4
},
{
user_id: 5
},
],
},
{
id: 3,
test_name: 'Test 2',
members: [{
user_id: 8
}]
}
];
const filtered = test_list.filter(
({ members }) => members.some(
({ user_id }) => user_id === 4
)
);
console.log(filtered);
You could use .reduce() and .filter() method of array to achieve required result.
Please check below working code snippet:
const arr = [{"id":1,"test_name":"Test 1","members":[{"user_id":3},{"user_id":4}]},{"id":2,"test_name":"Test 2","members":[{"user_id":4},{"user_id":5}]},{"id":3,"test_name":"Test 2","members":[{"user_id":8}]}];
const data = arr.reduce((r,{ members,...rest }) => {
let rec = members.filter(o => o.user_id === 4)
if(rec.length){
rest.members = rec;
r.push(rest);
}
return r;
},[]);
console.log(data);
Hope this works.
var members = item.members;
var filterById =members.filter((item1)=>{
return (item1.user_id===4)
});
return filterById.length > 0;
});
console.log(test_List_by_id)```