My Array of objects looks like this:
const categories = [{
id: 1,
name: 'level 1'
}, {
id: 2,
name: 'level 2'
}, {
id: 3,
name: 'level 3'
}];
I want to dynamically iterate over this categories array and output the name property as a string, separated with commas except the first object in the array
const output = 'level 2, level 3';
categories could potentially contain several objects.
const categories = [{
id: 1,
name: 'level 1'
}, {
id: 2,
name: 'level 2'
}, {
id: 3,
name: 'level 3'
}, ..., ..., ...];
however, it is important that the first object is not outputted
const categories = [{id: 1, name: 'level 1'}];
const output = '';
This is quite trivial
const getNames = arr => arr.map(item => item.name).slice(1).join(", "); // or slice first, map later
const categories1 = [{
id: 1,
name: 'level 1'
}, {
id: 2,
name: 'level 2'
}, {
id: 3,
name: 'level 3'
}];
const categories2 = [{
id: 1,
name: 'level 1'
}];
console.log("1:", getNames(categories1))
console.log("2:", getNames(categories2))
You could exclude first element by combining the use of destructing assignment and spread operator
const categories = [
{ id: 1, name: 'level 1' },
{ id: 2, name: 'level 2' },
{ id: 3, name: 'level 3' }
]
const [first, ...rest] = categories
const res = rest.map(cat => cat.name).join(', ')
console.log(res)
const categories = [{
id: 1,
name: 'level 1'
}, {
id: 2,
name: 'level 2'
}, {
id: 3,
name: 'level 3'
}];
const output = categories.reduce((ans, v, i) => {
return i === 1 ? v.name : (ans + ',' + v.name)
});
console.log(output)
This can be done in several ways. However, using Array.prototype.map() combined with Array.prototype.join() and Array.prototype.slice() is the easiest way.
const categories = [
{ id: 1, name: 'level 1' },
{ id: 2, name: 'level 2' },
{ id: 3, name: 'level 3' }
];
categories.slice(1).map(category => category.name).join(', ');
P.S.
using slice at first will make a new array starting from index 1 (second object)
using map will fill the new array with the value of "name" properties of all the objects in the array.
Finally, using join will convert the array to a string that consists of all the values in the array separated with the value you provide between the parentheses.
Related
I have an Array Object
const admins= [
{
id: 1,
name: 'Admin 1',
},
{
id: 2,
name: 'Admin 2',
},
{
id: 3,
name: 'Admin 3',
}
]
and another Array Object
const members= [
{
id: 1,
name: 'Name 1',
addedByAdminId: 1
},
{
id: 2,
name: 'Name 2',
addedByAdminId: 2
},
{
id: 3,
name: 'Name 3',
addedByAdminId: 3
}
]
I want to replace values of addedByAdminId of member arrayObject by names of admins where admins.id = addedByAdminId
My Current Code :
const objectC = members.forEach((item) => item.addedByAdminId= admins.filter(obj => obj.id === item.addedByAdminId)[0]['name']);
Expected Result :
objectC = [
{
id: 1,
name: 'Name 1',
addedByAdminId: 'Admin 1'
},
{
id: 2,
name: 'Name 2',
addedByAdminId: 'Admin 2'
},
{
id: 3,
name: 'Name 3',
addedByAdminId: 'Admin 3'
}
]
Error I am Getting :
Uncaught TypeError: Cannot read properties of undefined (reading 'name')
I am using React.
Welcome to stackoverflow.
This is what you want to do:
const newMembers = members.map(member => {
// get the admin name
const adminName = admins.find(it => it.id === member.addedByAdminId)?.name;
// create a new object with the spread operator
// containing everything from the memmber object
// overriding the property addedByAdminId with the variable adminName
return {...member, addedByAdminId: adminName}
});
Result
[
{
"id": 1,
"name": "Name 1",
"addedByAdminId": "Admin 1"
},
{
"id": 2,
"name": "Name 2",
"addedByAdminId": "Admin 2"
},
{
"id": 3,
"name": "Name 3",
"addedByAdminId": "Admin 3"
}
]
But this is what i suggest:
Instead of overriding a variable with a value that doesn't match this variable name just create a new one.
Code:
const newMembers = members.map(member => {
const adminName = admins.find(it => it.id === member.addedByAdminId)?.name;
return {...member, addedByAdminName: adminName}
});
Result
[
{
"id": 1,
"name": "Name 1",
"addedByAdminId": 1,
"addedByAdminName": "Admin 1"
},
{
"id": 2,
"name": "Name 2",
"addedByAdminId": 2,
"addedByAdminName": "Admin 2"
},
{
"id": 3,
"name": "Name 3",
"addedByAdminId": 3,
"addedByAdminName": "Admin 3"
}
]
So like this?
const admins = [
{
id: 1,
name: 'Admin 1',
},
{
id: 2,
name: 'Admin 2',
},
{
id: 3,
name: 'Admin 3',
}
]
const members = [
{
id: 1,
name: 'Name 1',
addedByAdminId: 1
},
{
id: 2,
name: 'Name 2',
addedByAdminId: 2
},
{
id: 3,
name: 'Name 3',
addedByAdminId: 3
}
]
const objC = members.map(({ id, name, addedByAdminId }) => ({
id,
name,
addedByAdminId: admins[addedByAdminId - 1].name
}))
console.log(objC)
this will replace addedByAdminId with the name when a matching record is present in admin array. if there is no matching record found to the addedByAdminId, the addedByAdminId will be not replaced.
{
id: 1,
name: 'Admin 1',
},
{
id: 2,
name: 'Admin 2',
},
{
id: 3,
name: 'Admin 3',
}
]
const members = [
{
id: 1,
name: 'Name 1',
addedByAdminId: 1
},
{
id: 2,
name: 'Name 2',
addedByAdminId: 2
},
{
id: 3,
name: 'Name 3',
addedByAdminId: 3
},
{
id: 4,
name: 'Name 4',
addedByAdminId: 4
}
]
const result = members.map(({ id, name, addedByAdminId }) => ({
id,
name,
addedByAdminId: admins.some(admin => admin.id === addedByAdminId) ? admins.find(admin => admin.id === addedByAdminId).name : addedByAdminId
}))
console.log(result);
I am trying to change the value of single key in an associative array which is inside another assoc array using javascript.
I have an array like this:
let arr = [{
id: 4,
name: 'test',
docs: [{
id: 1,
name: 'abc'
},{
id: 2,
name: 'xyz'
}]
}, {
id: 8,
name: 'test2',
docs: [{
id: 5,
name: 'abc'
},{
id: 7,
name: 'xyz'
}]
}]
I want to change the value of name of xyz to xyz (test), where test is name key of parent object and get final array as Output:
[{
id: 1,
name: 'abc (test)'
},
{
id: 2,
name: 'xyz (test)'
},
{
id: 5,
name: 'abc (test2)'
},
{
id: 7,
name: 'xyz (test2)'
}]
I am using approach.
let docs = new Array();
arr.forEach((item, index) => {
let docx = item.documents.map(item1 => {
item1.name = item1.name + " ("+item.name+")";
});
docs.push(docx);
});
return docs;
this is returning array of undefined array.
Try a flatMap
let arr = [{ id: 4, name: 'test', docs: [{ id: 1, name: 'abc' },{ id: 2, name: 'xyz' }] }, { id: 8, name: 'test2', docs: [{ id: 5, name: 'abc' },{ id: 7, name: 'xyz' }] }]
const output = arr.flatMap(item =>
item.docs.map(({id,name}) => ({ id, name: `${name} (${item.name})` }))
)
console.log(output)
There is an issue in your data, the docs inner array contains an object with duplicate keys:
let arr = [{
id: 4,
name: 'test',
docs: [{
id: 1,
name: 'abc',
id: 2, // <-- duplicate key
name: 'xyz' // <-- duplicate key
}]
},
If I remove the duplication, you can use this code to create a new object with the name value updated to xyz123 if the original value was xyz:
const original = [{
id: 4,
name: 'test',
docs: [{
id: 1,
name: 'abc'
}, {
id: 2,
name: 'xyz'
}]
}, {
id: 8,
name: 'test2',
docs: [{
id: 1,
name: 'abc'
}, {
id: 2,
name: 'xyz'
}]
}];
const updates = original.map(currentObject => {
const newObject = Object.assign(currentObject);
const newDocs = newObject.docs.map(doc => {
const newDoc = Object.assign(doc);
if (newDoc.name === "xyz") {
newDoc.name = "xyz123";
}
return newDoc;
});
newObject.docs = newDocs;
return newObject
});
console.log(updates);
I have two separate arrays of objects that I need to merge based if a specific key value matches. Might make more sense after analyzing the data:
Array 1
let categories = [
{ id: 5, slug: 'category-5', items: [] },
{ id: 4, slug: 'category-4', items: [] },
{ id: 3, slug: 'category-3', items: [] },
]
Array 2
let items = [
{ id: 5, data: [{ title: 'item title', description: 'item description' }] },
{ id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] },
{ id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] },
]
Expected Output
let mergedOutput = [
{ id: 5, slug: 'category-5',
items: [
{ title: 'item title', description: 'item description' },
{ title: 'item title 2', description: 'item description 2' }
]
},
{ id: 4, slug: 'category-4',
items: [
{ title: 'item title 4', description: 'item description 4' },
]
},
{ id: 3, slug: 'category-3', items: [] },
]
So....I need to add Array 2 to Array 1 if their id's match.
Array 1 will stay the same, but if Array 2 matches, the items property of Array 1 (empty) will be replaced by the data property of Array 2
I know this is a pretty basic / and redundant question, but I can't find the resources for my use case / object structure.
I was able to easily group arrays with lodash -- so if there is a similar solution with that library -- that would good! Or just some direction would suffice.
Thanks in advance!
You can loop first array and then use filter to get objects with same id as current element and add that items to current object.
let categories = [
{ id: 5, slug: 'category-5', items: [] },
{ id: 4, slug: 'category-4', items: [] },
{ id: 3, slug: 'category-3', items: [] },
]
let items = [
{ id: 5, data: [{ title: 'item title', description: 'item description' }] },
{ id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] },
{ id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] },
]
categories.forEach(function(e) {
var i = items.filter(a => a.id == e.id).map(a => a.data);
e.items = i;
})
console.log(categories)
You could reduce the items into categories:
let res = items.reduce((a, b) => {
let it = a.find(e => e.id === b.id);
if (! it) return a;
it.items = it.items.concat(b.data);
return a;
}, categories);
let categories = [{
id: 5,
slug: 'category-5',
items: []
},
{
id: 4,
slug: 'category-4',
items: []
},
{
id: 3,
slug: 'category-3',
items: []
},
];
let items = [{
id: 5,
data: [{
title: 'item title',
description: 'item description'
}]
},
{
id: 5,
data: [{
title: 'item title 2',
description: 'item description 2'
}]
},
{
id: 4,
data: [{
title: 'item title 4',
description: 'item description 4'
}]
},
];
let res = items.reduce((a, b) => {
let it = a.find(e => e.id === b.id);
if (! it) return a;
it.items = it.items.concat(b.data);
return a;
}, categories);
console.log(res);
It might be faster to get the ids in an object first, so we don't have to use find on the same id many times:
function merge(result, toMerge, mergeInto) {
let i = 0, hm = {};
for (let {id} of categories) {
hm[id] = i;
i++;
}
return toMerge.reduce((a,b) => {
let it = a[hm[b.id]];
if (!it) return a;
it[mergeInto] = it[mergeInto].concat(b.data);
return a;
}, result);
}
let categories = [
{ id: 5, slug: 'category-5', items: [] },
{ id: 4, slug: 'category-4', items: [] },
{ id: 3, slug: 'category-3', items: [] },
];
let items = [
{ id: 5, data: [{ title: 'item title', description: 'item description' }] },
{ id: 5, data: [{ title: 'item title 2', description: 'item description 2' }] },
{ id: 4, data: [{ title: 'item title 4', description: 'item description 4' }] },
];
function merge(result, toMerge, mergeInto) {
let i = 0, hm = {};
for (let {id} of categories) {
hm[id] = i;
i++;
}
return toMerge.reduce((a,b) => {
let it = result[hm[b.id]];
if (!it) return a;
it[mergeInto] = it[mergeInto].concat(b.data);
return a;
}, result);
}
console.log(merge(categories, items, 'items'));
I would make the categories as hash map and the key would be the id and iterate over all the items only.
then you get O(N) solution.
I was wondering if anyone could help figure out how i can set the value of a property in an object which can be found in a deep Array.
Below is an example of the Tree array
I would like to know how i can insert
var newObjectToInsert = {id: 999, name: 'new name'};
in the 'nodes' array of the object whose id === 3901
var tree = [
{
id: 1,
name: 'Level 1 - A',
nodes: [
{
id: 33,
name: 'Level 2 = A',
nodes: []
},
{
id: 21,
name: 'Level 2 = B',
nodes: []
}
]
},
{
id: 2,
name: 'Level 1 - B',
nodes: []
},
{
id: 3,
name: 'Level 1 - B',
nodes: [
{
id: 65,
name: 'Level 2 = A',
nodes: []
},
{
id: 124,
name: 'Level 2 = A',
nodes: [
{
id: 3901,
name: 'Level 3 - A'
},
{
id: 29182,
name: 'Level 3 - B',
nodes: [
{
id: 32423413,
name: 'Level 4 - A'
}
]
}
]
},
{
id: 534,
name: 'Level 2 = A',
nodes: []
}
]
},
];
You can use a native Array#some to achieve a recursive traversal. An advantage towards using this approach is it already provides a mechanism to stop the traversal once it finds the node that we want to insert the new object.
var inserted = tree.some(function cb(v) {
var nodes = v.nodes || [];
return v.id === nodeId?
(v.nodes = nodes).push(newObjectToInsert):
nodes.some(cb);
});
var tree = [{
id: 1,
name: 'Level 1 - A',
nodes: [{
id: 33,
name: 'Level 2 = A',
nodes: []
},
{
id: 21,
name: 'Level 2 = B',
nodes: []
}
]
},
{
id: 2,
name: 'Level 1 - B',
nodes: []
},
{
id: 3,
name: 'Level 1 - B',
nodes: [{
id: 65,
name: 'Level 2 = A',
nodes: []
},
{
id: 124,
name: 'Level 2 = A',
nodes: [{
id: 3901,
name: 'Level 3 - A'
},
{
id: 29182,
name: 'Level 3 - B',
nodes: [{
id: 32423413,
name: 'Level 4 - A'
}]
}
]
},
{
id: 534,
name: 'Level 2 = A',
nodes: []
}
]
},
];
var newObjectToInsert = {id: 999, name: 'new name'};
var nodeId = 3901;
var inserted = tree.some(function cb(v) {
var nodes = v.nodes || [];
return v.id === nodeId?
(v.nodes = nodes).push(newObjectToInsert):
nodes.some(cb);
});
console.log(tree);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
You have a recursive structure. So you visit all items you need a visitor.
Pseudo code:
function visit(visitor, tree) {
visitor(tree);
items.nodes.forEach(subTree => visit(visitor, subTree));
}
And use
visit(node => {
if (node.id === 'whatever'){
node.push({yournode});
}
}, tree);
I have this array of objects:
[
{
id: 1,
name: 'test 1'
},
{
id: 2,
name: 'test 2'
},
{
id: 3,
name: 'test 3'
},
{
id: 4,
name: 'test 4'
}
]
I have this array of IDs:
[1, 3]
How can I select all objects whose id property exists in the IDs array?
var ids = [1, 3];
var found = _.where(items, function (item) {
return ids.indexOf(item.id) !== -1;
});