Reputation: 2833
I have a question about filtering with ES6:
I have some data which I need to filter with other objects
My data is:
let data = [
{
id: 1,
names: ['A', 'B']
},
{
id: 2,
names: ['C']
}
]
I have another object as:
let nameValues = [
{
name: 'A',
selected: false
},
{
name: 'B',
selected: true
},
{
name: 'C',
selected: false
},
{
name: 'D',
selected: true
}
]
I'm first getting selected == true
items in selectedNames
with:
let selectedNames = nameValues.filter(function(item) {
return item.selected
})
and I'm getting result:
selectedNames = [
{
name: 'A',
selected: true
},
{
name: 'D',
selected: true
}
]
and I need to compare it with data
, getting items in data
where item.names
have selectedNames
in it.
I don't need exactly matching -- I need the items in data object which have in their names array my selectedNames
object name
values:
In this case I need to get like this result of my data object:
Here is item not matching 100% with my selectedNames
but it have one of these values which I am looking for
let data = [
{
id: 1,
names: ['A', 'B']
},
]
How to do that with es6?
Upvotes: 1
Views: 289
Reputation: 397
Obviously Names will repeat in Data object
const nameValues = [
{
name: "A",
selected: false
},
{
name: "B",
selected: true
},
{
name: "C",
selected: true
},
{
name: "D",
selected: false
}
];
let data = [
{
id: 1,
names: ["A", "B"]
},
{
id: 2,
names: ["C"]
},
{
id: 3,
names: ["C", "D"]
}
];
let selectedNames = nameValues
.filter(item => item.selected)
.reduce((acc, item) => {
const selected = data.filter(dataItem => {
return (
dataItem.names.includes(item.name) &&
!acc.some(i => i.id === dataItem.id)
);
});
return [...acc, ...selected];
}, []);
console.log(selectedNames);
Upvotes: 0
Reputation: 1156
Just two loop, example using reduce
:
let data = [
{
id: 1,
names: ['A', 'B']
},
{
id: 2,
names: ['C']
}
]
let selectedNames = [
{
name: 'A',
selected: true
},
{
name: 'D',
selected: true
}
]
selectedNames.reduce((result, selectedName) => {
data.forEach(item => {
if (item.names.includes(selectedName.name)) {
result.push(item)
}
})
return result
}, [])
Upvotes: 0
Reputation: 6005
Your approach was right. I just stored the selectedNames as an array for easier lookup.
In the data.filter, you can check if the some
name is available in the selectedNames array
let data = [
{
id: 1,
names: ['A', 'B']
},
{
id: 2,
names: ['C']
}
]
let nameValues = [
{
name: 'A',
selected: false
},
{
name: 'B',
selected: true
},
{
name: 'C',
selected: false
},
{
name: 'D',
selected: true
}
]
let selectedNames = nameValues.filter(item => item.selected).map(x => x.name);
let result = data.filter(obj => obj.names.some(name => selectedNames.includes(name)));
console.log(result);
Upvotes: 2
Reputation: 5422
You could use a nested for loop over both arrays and check whether each individual selected name is in any of the data elements:
const data = [
{ id: 1, names: ['A', 'B'] },
{ id: 2, names: ['C'] },
]
const selectedNames = [
{ name: 'A', selected: true },
{ name: 'D', selected: true },
{ name: 'B', selected: true },
]
const result = [];
for (const element of data) {
for (const name of selectedNames) {
if (element.names.includes(name.name) && !result.includes(element)) {
result.push(element);
}
}
}
console.log( result );
Upvotes: 0