conditionally map an array of objects - javascript

I have two array of objects and I need to introduce the name in a new array where listOfRegistries.Id === listOfTargets.regId
this.listOfRegistries = [
{ id: '123', name: 'name1' },
{ id: '245', name: 'name2' },
];
this.listOfTargets = [
{ regId: '123',key: 'value1' },
{ regId: '245', key: 'value2' },
];
I need to achieve this:
this. listOfTargetsNew = [
{ regId: '123',key: 'value1', name: 'name1' },
{ regId: '245', key: 'value2', name: 'name2' },
];
This is what I'm trying with no result
this.listOfTargetsNew = this.listOfTargets.map((el, index)=> {
if( this.listOfRegistries[index].id === el.regId) {
el['name'] = this.listOfRegistries[index].name;
return el;
}
});
Thank you very much for your responses.

You can easily map over the array and find the correct name via the find method.
const listOfRegistries = [
{ id: '123', name: 'name1' },
{ id: '245', name: 'name2' },
];
const listOfTargets = [
{ regId: '123',key: 'value1' },
{ regId: '245', key: 'value2' },
];
const listOfTargetsNew = listOfTargets.map((obj) => {
const registry = listOfRegistries.find(({ id }) => id === obj.regId);
return {...obj, name: registry.name};
});
console.log(listOfTargetsNew);

You could store the registries in an object and map the other array with addtional property.
const
listOfRegistries = [{ id: '123', name: 'name1' }, { id: '245', name: 'name2' }],
listOfTargets = [{ regId: '123', key: 'name1' }, { regId: '245', key: 'name2' }],
registries = Object.fromEntries(listOfRegistries.map(({ id, name }) => [id, name])),
listOfTargetsNew = listOfTargets.map(o => ({ ...o, name: registries[o.regId] }));
console.log(listOfTargetsNew);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How to change object value in array with objects with if/else in JS

I have an array with objects. I need to find item with current name and change it.
const example = [
{
id: '1234',
desc: 'sample1',
items: [
itemsName: [
{ id: 1, name: 'name1' },
{ id: 2, name: 'testItem2' }
],
id: 888,
]
},
{
id: '3456',
desc: 'sample2',
items: [
itemsName: [
{ id: 1, name: 'name2' },
{ id: 2, name: 'testItem3' }
],
id: 889,
]
},
I try to do in this way, but it's not working.
I get construction like (5) 
[Array(1), Array(1)]
instead of 
[{…}, {…}]
const findName = (name, changedName) => {
const result = example?.map((group) =>
group.items.map((group) =>
group.itemsName?.map((i) => {
if (i.name === name) return i.name === changedName;
return null;
})
)
);
}
findName('name1', 'name2')
let findName1 = (name, changedName) => {
const result = example?.map((group) =>
group.items.map((group) =>
group.itemsName?.map((i) => {
if (i.name === name) return i.name = changedName;
return null;
})
)
);
}
This will work with following object (your object declaration seems to be wrong)
const example = [
{
id: '1234',
desc: 'sample1',
items: [
{itemsName: [
{ id: 1, name: 'name1' },
{ id: 2, name: 'testItem2' }
],
id: 888,}
]
},
{
id: '3456',
desc: 'sample2',
items: [
{itemsName: [
{ id: 1, name: 'name2' },
{ id: 2, name: 'testItem3' }
],
id: 889,}
]
}]

Subset Json object in Javascript

Given an array of json object like this below, (the json object such as "name2" and "name4" will definitely have only one key-value)
[
{
abc: 123,
id: '18263322',
name: 'name1'
},
{ name: 'name2' },
{
abc: 456,
id: '18421634',
name: 'name3'
},
{ name: 'name4' }
]
How can I subset this so that I have two array of json objects:
[
{
abc: 123,
id: '18263322',
name: 'name1'
},
{
abc: 456,
id: '18421634',
name: 'name3'
}
]
and
[
{ name: 'name2' },
{ name: 'name4' }
]
You can use reduce here
const arr = [
{
abc: 123,
id: "18263322",
name: "name1",
},
{ name: "name2" },
{
abc: 456,
id: "18421634",
name: "name3",
},
{ name: "name4" },
];
const [single, multiple] = arr.reduce((acc, curr) => {
Object.keys(curr).length === 1 ? acc[0].push(curr) : acc[1].push(curr);
return acc;
},[[], []]
);
console.log(single);
console.log(multiple);
You can also do something like
const [single, multiple] = arr.reduce((acc, curr) => {
acc[Object.keys(curr).length === 1 ? 0 : 1].push(curr);
return acc;
},[[], []]);
using filter
const arr = [
{
abc: 123,
id: "18263322",
name: "name1",
},
{ name: "name2" },
{
abc: 456,
id: "18421634",
name: "name3",
},
{ name: "name4" },
];
const single = arr.filter((o) => Object.keys(o).length === 1);
const multiple = arr.filter((o) => Object.keys(o).length !== 1);
console.log(single);
console.log(multiple);

Merge/Add an object into an array - Javscript

I have an two arrays of objects. My goal is to replace an object from the second array into the first one based upon 'id'. I have a working solution, but would like to extend it by adding the object to the first array if a value isnt found. Please advice.
function mergeById(arr) {
return {
with: function(arr2) {
return _.map(arr, item => {
return _.find(arr2, obj => obj.id === item.id) || item
})
}
}
}
var result = mergeById([{
id: '124',
name: 'qqq'
},
{
id: '589',
name: 'www'
},
{
id: '567',
name: 'rrr'
}
])
.with([{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}])
console.log(result);
/**
[
{
"id": "124",
"name": "ttt"
},
{
"id": "589",
"name": "www"
},
{
"id": "567",
"name": "rrr"
},
{
id: '45',
name: 'yyy'
}
]
**/
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
Please advice.
You need to filter the second array and add the values who have no common id.
function mergeById(arr) {
return {
with: function(arr2) {
return [
..._.map(arr, item => _.find(arr2, obj => obj.id === item.id) || item),
..._.filter(arr2, item => !_.some(arr, obj => obj.id === item.id))
];
}
}
}
var result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
.with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
A shorter approach with a Map and single loops for every array.
function mergeById(array) {
const
add2map = (m, o) => m.set(o.id, o),
map = array.reduce(add2map, new Map);
return {
with: function(array2) {
return Array.from(array2
.reduce(add2map, map)
.values()
);
}
}
}
var result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
.with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Use _.differenceBy(arr2, arr, 'id') to find all items that appear in arr2 that doesn't have a counterpart in arr by id, and concat them to the results of the _.map() action.
Note: instead using _.find() (O(n)) on each iteration, iterate arr2 once with _.keyBy() (O(n)) to create a dictionary { [id]: item }, and then get the items in O(1).
const mergeById = arr => ({
with(arr2) {
const arr2Dict = _.keyBy(arr2, 'id')
return _.map(arr, item => arr2Dict[item.id] || item)
.concat(_.differenceBy(arr2, arr, 'id'))
}
})
const result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
.with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }])
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>
You can replace/add in a single loop by concating both arrays, reducing to a Map, and just adding the items by id to the Map:
const mergeById = arr => ({
with(arr2) {
return Array.from(
[...arr, ...arr2]
.reduce((r, o) => r.set(o.id, o), new Map)
.values()
)
}
})
const result = mergeById([{ id: '124', name: 'qqq' }, { id: '589', name: 'www' }, { id: '567', name: 'rrr' } ])
.with([{ id: '124', name: 'ttt' }, { id: '45', name: 'yyy' }])
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.20/lodash.min.js"></script>

How would you change values/add to nested object data inside array of objects using Javascript?

const beers = [
{
id: '100',
name: 'stoneys'
},
{
id: '200',
name: 'budweiser'
},
{
id: '300',
name: 'miller'
},
{
id: '400',
name: 'corona'
}
];
const people = [
{
name: 'steve',
teams: [
{
name: 'pirates',
beers: ['100']
},
{
name: 'penguins',
beers: ['300']
}
]
},
{
name: 'jim',
teams: [
{
name: 'indians',
beers: ['200']
},
{
name: 'blue jackets',
beers: ['100', '400']
}
]
}
];
let newPeople = people.map(fan => {
fan.teams.map(team => {
team.beers.map(beer => beers.filter(brand => brand.id === beer)[0])
});
});
Above is a sample I put together to best demonstrate my question. I am having trouble understanding why nested mapping (.map()) of object arrays is not allowing me to alter the nested data. When I console log results, I am either getting an "[undefined, undefined]' or the unchanged "people" array.
I would like to return the same array as "people" except replace the nested "beers" array (people.teams.beers[]) with corresponding objects from the "beers" array. Example of a successful result below:
{
name: 'steve',
teams: [
{
name: 'pirates',
beers: [
{
id: '100',
name: 'stoneys'
}
]
},
{
name: 'penguins',
beers: [
{
id: '300',
name: 'miller'
}
]
}
]
}
Array.map expects a function which takes single array element as parameter and returns a mapped value. In your case you're not returning any value from mapping functions therefore you're getting undefined twice
const beers = [
{
id: '100',
name: 'stoneys'
},
{
id: '200',
name: 'budweiser'
},
{
id: '300',
name: 'miller'
},
{
id: '400',
name: 'corona'
}
];
const people = [
{
name: 'steve',
teams: [
{
name: 'pirates',
beers: ['100']
},
{
name: 'penguins',
beers: ['300']
}
]
},
{
name: 'jim',
teams: [
{
name: 'indians',
beers: ['200']
},
{
name: 'blue jackets',
beers: ['100', '400']
}
]
}
];
let newPeople = people.map(fan => {
let teams = fan.teams.map(team => {
let beer = team.beers.map(beer => beers.filter(brand => brand.id === beer)[0]);
return { name: team.name, beers: beer }
});
return { name: fan.name, teams: teams }
});
console.log(newPeople);

Map list of objects with sub array of objects

I have this data structure that i want to map in an es6 one-liner fashion:
const vehicles = [
{
id: 'vehicle1',
items: [
{
id: 'contract1'
name: 'Contract 1',
},
],
},
{
id: 'vehicle1',
items: [
{
id: 'contract2'
name: 'Contract 2',
},
],
},
{
id: 'vehicle2',
items: [
{
id: 'contract3'
name: 'Contract 3',
},
],
},
{
id: 'vehicle2',
items: [
{
id: 'contract4'
name: 'Contract 4',
},
],
},
]
I would like to collect this in a list like this:
const result = [
{
id: 'vehicle1',
items: [
{
id: 'contract1'
name: 'Contract 1',
},
{
id: 'contract2'
name: 'Contract 2',
},
],
},
{
id: 'vehicle2',
items: [
{
id: 'contract3'
name: 'Contract 3',
},
{
id: 'contract4'
name: 'Contract 4',
},
],
},
]
So the vehicles in list is unique and items is in one list.
I tried this but it only collects vehicles in list:
const res = vehicles.reduce((acc, vehicle) => acc.set(vehicle.id, vehicle), new Map())
How can I do this the 'ES6 way'?
Map would be not a good choice for this type of result, Map used mostly when you have to modify and get same structure. You can use reduce for this.
var data = [{
id: 'vehicle1',
items: [{
id: 'contract1',
name: 'Contract 1'
}]
},
{
id: 'vehicle1',
items: [{
id: 'contract2',
name: 'Contract 2'
}]
},
{
id: 'vehicle2',
items: [{
id: 'contract3',
name: 'Contract 3'
}]
},
{
id: 'vehicle2',
items: [{
id: 'contract4',
name: 'Contract 4'
}]
}
];
var result = {};
data.forEach(val => {
if (result[val.id])
result[val.id].items = result[val.id].items.concat(val.items);
else
result[val.id] = val
});
result = Object.values(result);
console.log(result);
You were on the right path. Here it is:
const res = vehicles.reduce((m,v)=>m.set(v.id, [...v.items, ...(m.get(v.id)||[])]), new Map)
This use array destructuring to concat items.
You can use Array.prototype.reduce to aggregate the input by id and Object.keys to get the output in the desired format
const vehicles=[{id:'vehicle1',items:[{id:'contract1',name:'Contract 1'}]},{id:'vehicle1',items:[{id:'contract2',name:'Contract 2'}]},{id:'vehicle2',items:[{id:'contract3',name:'Contract 3'}]},{id:'vehicle2',items:[{id:'contract4',name:'Contract 4'}]}];
const grouped = vehicles.reduce((all, {id, items}) => {
if (!all.hasOwnProperty(id)) all[id] = { id, items: [] };
all[id].items.push(...items);
return all;
}, {});
const result = Object.keys(grouped).map(k => grouped[k]);
console.log(result);
Not a one-liner but it returns desired result and uses ES6 Map.
const data = [{"id":"vehicle1","items":[{"id":"contract1","name":"Contract 1"}]},{"id":"vehicle1","items":[{"id":"contract2","name":"Contract 2"}]},{"id":"vehicle2","items":[{"id":"contract3","name":"Contract 3"}]},{"id":"vehicle2","items":[{"id":"contract4","name":"Contract 4"}]}]
const res = data.reduce((acc, {id, items}) => {
if(!acc.get(id)) acc.set(id, {id, items});
else acc.get(id).items.push(...items);
return acc;
}, new Map())
console.log([...res.values()])
Well, its not a one liner but it can be...if you delete all the line breaks :D
const convert = () => {
const vMap = vehicles.reduce((acc, vehicle) => {
if (acc[vehicle.id]) {
acc[vehicle.id].items.push(...vehicle.items);
} else {
acc[vehicle.id] = vehicle;
}
return acc;
}, {});
return Object.keys(vMap).map(k => vMap[k]);
};
convert();
Nearly, you could get the grouped items in a map and map the map with the wanted id and itmes property.
const
vehicles = [{ id: 'vehicle1', items: [{ id: 'contract1', name: 'Contract 1', }] }, { id: 'vehicle1', items: [{ id: 'contract2', name: 'Contract 2', }] }, { id: 'vehicle2', items: [{ id: 'contract3', name: 'Contract 3', }] }, { id: 'vehicle2', items: [{ id: 'contract4', name: 'Contract 4' }] }],
result = Array.from(
vehicles.reduce((acc, { id, items }) =>
acc.set(id, (acc.get(id) || []).concat(items)), new Map()),
([id, items]) => ({ id, items })
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories