I have 2 array of objects
Tasks
[{
name: "test",
type: "one"
},
{
name: "test2",
type: 'two'
}]
activities
[{
name: "test",
type: "one"
},
{
name: "test2",
type: 'two'
},
{
name: "test3",
type: "three"
}]
How can I filter the activities array by properties of the tasks array? I would like this outcome.
activities
[{
name: "test",
type: "one"
},
{
name: "test2",
type: 'two'
}]
I have tried using .filter(), but that returns an empty collection.
let tests = activities.filter(x => tasks.includes(x.type));
How can I achieve that in Javascript?
filter
is the right tool, but includes
is not. The entries in tasks
are objects, not strings; none of them will match any of the types in tests
.
Instead, the simple version uses some
to see if any entries in tasks
match the type of the activity being tested:
let tests = activities.filter(a => tasks.some(t => t.type == a.type));
Live Example:
const tasks = [ { name: "test", type: "one" }, { name: "test2", type: 'two' } ]; const activities = [ { name: "test", type: "one" }, { name: "test2", type: 'two' }, { name: "test3", type: "three" } ]; let tests = activities.filter(a => tasks.some(t => t.type == a.type)); console.log(tests);
.as-console-wrapper { max-height: 100% !important; }
Naturally, that means at least partially re-traversing tasks
for each entry in activities
. For the examples you've shown, that's absolutely fine; if tasks
is hundreds of thousands of entries long or this is done in a tight loop, not so much. :-)
In that situation, you could give yourself a set of known types from tasks
in advance, then just test against the set:
const knownTypes = new Set();
for (const task of tasks) {
knownTypes.add(task.type);
}
let tests = activities.filter(a => knownTypes.has(a.type));
Live Example:
const tasks = [ { name: "test", type: "one" }, { name: "test2", type: 'two' } ]; const activities = [ { name: "test", type: "one" }, { name: "test2", type: 'two' }, { name: "test3", type: "three" } ]; const knownTypes = new Set(); for (const task of tasks) { knownTypes.add(task.type); } let tests = activities.filter(a => knownTypes.has(a.type)); console.log(tests);
.as-console-wrapper { max-height: 100% !important; }
Alternately, instead of Set
you could also use an object for knownTypes
, creating it via Object.create(null)
on the off-chance any of your types happens to be something with the same name as a property on Object.prototype
:
const knownTypes = Object.create(null);
for (const task of tasks) {
knownTypes[task.type] = true;
}
let tests = activities.filter(a => knownTypes[a.type]);
Live Example:
const tasks = [ { name: "test", type: "one" }, { name: "test2", type: 'two' } ]; const activities = [ { name: "test", type: "one" }, { name: "test2", type: 'two' }, { name: "test3", type: "three" } ]; const knownTypes = Object.create(null); for (const task of tasks) { knownTypes[task.type] = true; } let tests = activities.filter(a => knownTypes[a.type]); console.log(tests);
.as-console-wrapper { max-height: 100% !important; }
Almost there. Try using the .some
array method to check if the item is present, since includes
won't work for a nested property.
const tasks = [{ name: "test", type: "one" }, { name: "test2", type: 'two' }] const activities = [{ name: "test", type: "one" }, { name: "test2", type: 'two' }, { name: "test3", type: "three" }] let tests = activities.filter(x => tasks.some(t => t.type === x.type)); console.log(tests)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.