This works, but I'm wondering if there is a better way to filter by index:
a = [10,20,30,40]
b = [1,3]
a.filter((x,i) => b.includes(i))
// [20, 40]
This works, but I'm wondering if there is a better way to filter by index:
a = [10,20,30,40]
b = [1,3]
a.filter((x,i) => b.includes(i))
// [20, 40]
Share
Improve this question
edited Apr 30, 2017 at 16:38
nachocab
asked Apr 30, 2017 at 16:35
nachocabnachocab
14.4k21 gold badges104 silver badges158 bronze badges
4
|
3 Answers
Reset to default 12Another way would be b.map(aIndex => a[aIndex])
. If b
is shorter than a
this could also be faster. However if there are indexes in b
that do not belong in a
, you would end up with undefined
"holes" in the array.
EDIT
Looking a bit into Array.includes
, looks like it will run in O(n) for unsorted arrays.
If we say A = a.length
and B = b.length
, your solution from the question should run in O(A * B).
The second solution (with map) will run in O(B). To fix the undefined
holes, you could add a .filter(element => typeof element !== 'undefined')
.
The final solution would then be b.map(i => a[i]).filter(e => typeof e !== 'undefined')
. This now runs in O(2 * B), which should still be better than O(A * B).
I think your solution is just great. map
is a great solution too.
For the record, you could use a for...of
loop, but it becomes much more complex for nothing...
let a = [10, 20, 30, 40],
b = [1, 3];
let res = [];
for (const entry of a.entries()) {
if (b.includes(entry[0])) {
res.push(entry[1]);
}
}
console.log(res);
This (and more) can be done with Lodash's at
function:
_.at([10, 20, 30, 40], [1, 3]) // [20, 40]
_.at(['a', 'b'], [0, 1, 1, 0]) // ['a', 'b', 'b', 'a']
b.map(i => a[i])
assumingb
always carries indices mapping on some item ina
– Redu Commented Apr 30, 2017 at 16:41a.select(b)
– nachocab Commented Apr 30, 2017 at 16:44