Reputation: 5760
I have two arrays selectedData
and allServices
selectedData = [
{ id: 5 },
{ id: 6 }
];
allServices = [
{ id: 3, selected: false },
{ id: 4, selected: false },
{ id: 5, selected: false },
{ id: 6, selected: false },
{ id: 7, selected: false },
];
I use the function to compare and change allServices
structure.
const changeStructure = (selectedData, allServices) => {
selectedData.services.map((_item, index) => {
allServices.map((value, i) => {
if (value.id === _item.id) {
allServices[i].selected = true;
} else {
allServices[i].selected = false;
}
})
})
console.log('final allServices', allServices);
return allServices;
}
console.log final allServices
is
[
{ id: 3, selected: false },
{ id: 4, selected: false },
{ id: 5, selected: false },
{ id: 6, selected: true },
{ id: 7, selected: false },
];
I thought my allServices
should be
[
{ id: 3, selected: false },
{ id: 4, selected: false },
{ id: 5, selected: true },
{ id: 6, selected: true },
{ id: 7, selected: false },
];
I have no idea why this is happening. Any suggestion would be appreciated.
Upvotes: 0
Views: 669
Reputation: 50684
Your issue is that each time you iterate over your selectedData
array using the outer .map()
you're changing all the item ids you previously set to true
back to false
. Instead, you should use .map()
by returning a new item each time you iterate. This can be done efficiently by creating a new Set
of all ids which are in your selectedData
and changing the selected
property based on whether the set .has()
the id
of the current object:
const selectedData = [ { id: 5 }, { id: 6 } ];
const allServices = [ { id: 3, selected: false }, { id: 4, selected: false }, { id: 5, selected: false }, { id: 6, selected: false }, { id: 7, selected: false } ];
const lut = new Set(selectedData.map(({id}) => id));
const res = allServices.map(obj => ({...obj, selected: lut.has(obj.id)}));
console.log(res);
Upvotes: 4
Reputation: 35222
It will only consider the last item in selectedData
array because every selected: true
value set is being reset by the else
block.
Another option is to create a Set
of all the id
s from selectedData
. Loop through allServices
and update the selected
value based on whether the Set has
the current object's id
const selectedData=[{id:5},{id:6}],
allServices=[{id:3,selected:false},{id:4,selected:false},{id:5,selected:false},{id:6,selected:false},{id:7,selected:false},];
const set = new Set(selectedData.map(o => o.id));
allServices.forEach(o => o.selected = set.has(o.id))
console.log(allServices)
Upvotes: 2
Reputation: 1527
Here is my solution. It looks quite simple.
const changeStructure = (selectedData, allServices) => {
allServices.forEach(item => {
item.selected = selectedData.some(sel => sel.id === item.id);
});
console.log('final allServices', allServices);
return allServices;
}
Upvotes: 0
Reputation: 2438
Can you try simple code:
const selectedData = [
{ id: 5 },
{ id: 6 }
];
const allServices = [
{ id: 3, selected: false },
{ id: 4, selected: false },
{ id: 5, selected: false },
{ id: 6, selected: false },
{ id: 7, selected: false }
];
const res = allServices.map(service => ({...service , selected: selectedData.findIndex(selected => selected.id === service.id) >-1 }));
console.log(res);
Upvotes: 0
Reputation: 1
You can make a loop with allServices
and compare the id
in each element with the id
of elements inside selectedData
using forEach
function. Like this:
var selectedData = [
{ id: 5 },
{ id: 6 }
];
var allServices = [
{ id: 3, selected: false },
{ id: 4, selected: false },
{ id: 5, selected: false },
{ id: 6, selected: false },
{ id: 7, selected: false },
];
allServices.forEach(x => x.selected = selectedData.find(a => a.id === x.id) !== undefined);
console.log(allServices);
Upvotes: 1
Reputation: 198324
There are no breaks. You inspect all possible pairs, and assign to allServices[i].selected
once for each value in selectedData
. So allServices[3].selected
is assigned with false
and again false
; allServices[6].selected
is assigned with false
, then true
; but allServices[5].selected
is assigned with true
, then overwritten by false
.
You would want the loops reversed, so that the inner one could be broken out of. Better yet, use some
.
const changeStructure = (selectedData, allServices) => {
allServices.forEach(value => {
value.selected = selectedData.some(selected => selected.id == value.id)
})
console.log('final allServices', allServices);
return allServices;
}
Upvotes: 1
Reputation: 2143
You need to remove the else
block from your code, which is updating the previous ids to false on mismatch.
const changeStructure = (selectedData, allServices) => {
selectedData.services.map((_item, index) => {
allServices.map((value, i) => {
if (value.id === _item.id) {
allServices[i].selected = true;
}
})
})
console.log('final allServices', allServices);
return allServices;
}
Upvotes: 2