I am trying to find the index of all the instances of an element, say, "Nano", in a JavaScript array.
var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
I tried jQuery.inArray, or similarly, .indexOf(), but it only gave the index of the last instance of the element, i.e. 5 in this case.
How do I get it for all instances?
This question is related to
javascript
jquery
arrays
findIndex
retrieves only the first index which matches callback output. You can implement your own findIndexes
by extending Array , then casting your arrays to the new structure .
class EnhancedArray extends Array {_x000D_
findIndexes(where) {_x000D_
return this.reduce((a, e, i) => (where(e, i) ? a.concat(i) : a), []);_x000D_
}_x000D_
}_x000D_
/*----Working with simple data structure (array of numbers) ---*/_x000D_
_x000D_
//existing array_x000D_
let myArray = [1, 3, 5, 5, 4, 5];_x000D_
_x000D_
//cast it :_x000D_
myArray = new EnhancedArray(...myArray);_x000D_
_x000D_
//run_x000D_
console.log(_x000D_
myArray.findIndexes((e) => e===5)_x000D_
)_x000D_
/*----Working with Array of complex items structure-*/_x000D_
_x000D_
let arr = [{name: 'Ahmed'}, {name: 'Rami'}, {name: 'Abdennour'}];_x000D_
_x000D_
arr= new EnhancedArray(...arr);_x000D_
_x000D_
_x000D_
console.log(_x000D_
arr.findIndexes((o) => o.name.startsWith('A'))_x000D_
)
_x000D_
I just want to update with another easy method.
You can also use forEach method.
var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
var result = [];
Cars.forEach((car, index) => car === 'Nano' ? result.push(index) : null)
["a", "b", "a", "b"]
.map((val, index) => ({ val, index }))
.filter(({val, index}) => val === "a")
.map(({val, index}) => index)
=> [0, 2]
You can write a simple readable solution to this by using both map
and filter
:
const nanoIndexes = Cars
.map((car, i) => car === 'Nano' ? i : -1)
.filter(index => index !== -1);
EDIT: If you don't need to support IE/Edge (or are transpiling your code), ES2019 gave us flatMap, which lets you do this in a simple one-liner:
const nanoIndexes = Cars.flatMap((car, i) => car === 'Nano' ? i : []);
const indexes = cars
.map((car, i) => car === "Nano" ? i : null)
.filter(i => i !== null)
We can use Stack and push "i" into the stack every time we encounter the condition "arr[i]==value"
Check this:
static void getindex(int arr[], int value)
{
Stack<Integer>st= new Stack<Integer>();
int n= arr.length;
for(int i=n-1; i>=0 ;i--)
{
if(arr[i]==value)
{
st.push(i);
}
}
while(!st.isEmpty())
{
System.out.println(st.peek()+" ");
st.pop();
}
}
You can use Polyfill
if (!Array.prototype.filterIndex) {
Array.prototype.filterIndex = function (func, thisArg) {
'use strict';
if (!((typeof func === 'Function' || typeof func === 'function') && this))
throw new TypeError();
let len = this.length >>> 0,
res = new Array(len), // preallocate array
t = this, c = 0, i = -1;
let kValue;
if (thisArg === undefined) {
while (++i !== len) {
// checks to see if the key was set
if (i in this) {
kValue = t[i]; // in case t is changed in callback
if (func(t[i], i, t)) {
res[c++] = i;
}
}
}
}
else {
while (++i !== len) {
// checks to see if the key was set
if (i in this) {
kValue = t[i];
if (func.call(thisArg, t[i], i, t)) {
res[c++] = i;
}
}
}
}
res.length = c; // shrink down array to proper size
return res;
};
}
Use it like this:
[2,23,1,2,3,4,52,2].filterIndex(element => element === 2)
result: [0, 3, 7]
Note: MDN gives a method using a while loop:
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
indices.push(idx);
idx = array.indexOf(element, idx + 1);
}
I wouldn't say it's any better than other answers. Just interesting.
More simple way with es6 style.
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
//Examples:
var cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
indexOfAll(cars, "Nano"); //[0, 3, 5]
indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []
Just to share another method, you can use Function Generators to achieve the result as well:
function findAllIndexOf(target, needle) {_x000D_
return [].concat(...(function*(){_x000D_
for (var i = 0; i < target.length; i++) if (target[i] === needle) yield [i];_x000D_
})());_x000D_
}_x000D_
_x000D_
var target = "hellooooo";_x000D_
var target2 = ['w','o',1,3,'l','o'];_x000D_
_x000D_
console.log(findAllIndexOf(target, 'o'));_x000D_
console.log(findAllIndexOf(target2, 'o'));
_x000D_
Another alternative solution is to use Array.prototype.reduce()
:
["Nano","Volvo","BMW","Nano","VW","Nano"].reduce(function(a, e, i) {
if (e === 'Nano')
a.push(i);
return a;
}, []); // [0, 3, 5]
N.B.: Check the browser compatibility for reduce
method and use polyfill if required.
This worked for me:
let array1 = [5, 12, 8, 130, 44, 12, 45, 12, 56];
let numToFind = 12
let indexesOf12 = [] // the number whose occurrence in the array we want to find
array1.forEach(function(elem, index, array) {
if (elem === numToFind) {indexesOf12.push(index)}
return indexesOf12
})
console.log(indexesOf12) // outputs [1, 5, 7]
Another approach using Array.prototype.map() and Array.prototype.filter():
var indices = array.map((e, i) => e === value ? i : '').filter(String)
Source: Stackoverflow.com