如何查找数组中所有元素出现的索引?

我试图在一个 JavaScript 数组中找到一个元素的所有实例的索引,比如“ Nano”。

var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];

我尝试了 数组,或者类似的 . indexOf (),但是它只给出了元素最后一个实例的索引,在本例中是5。

我如何得到它的所有实例?

256539 次浏览

.indexOf()有一个可选的第二个参数,用于指定要开始搜索的索引,因此可以在循环中调用它来查找特定值的所有实例:

function getAllIndexes(arr, val) {
var indexes = [], i = -1;
while ((i = arr.indexOf(val, i+1)) != -1){
indexes.push(i);
}
return indexes;
}


var indexes = getAllIndexes(Cars, "Nano");

实际上并不清楚如何使用索引,所以我的函数将它们作为数组返回(如果没有找到索引值,则返回空数组) ,但是您可以对循环中的单个索引值执行其他操作。

更新: 根据 VisioN 的评论,一个简单的 for 循环可以更有效地完成同样的工作,并且更容易理解,因此更容易维护:

function getAllIndexes(arr, val) {
var indexes = [], i;
for(i = 0; i < arr.length; i++)
if (arr[i] === val)
indexes.push(i);
return indexes;
}

另一种解决方案是使用 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]

注意: 检查 浏览器兼容性reduce方法,必要时使用 填料

使用 Map ()Filter ()的另一种方法:

var indices = array.map((e, i) => e === value ? i : '').filter(String)

findIndex只检索与回调输出匹配的第一个索引。您可以通过扩展 Array 实现自己的 findIndexes,然后将数组强制转换为新结构。

class EnhancedArray extends Array {
findIndexes(where) {
return this.reduce((a, e, i) => (where(e, i) ? a.concat(i) : a), []);
}
}
/*----Working with simple data structure (array of numbers) ---*/


//existing array
let myArray = [1, 3, 5, 5, 4, 5];


//cast it :
myArray = new EnhancedArray(...myArray);


//run
console.log(
myArray.findIndexes((e) => e===5)
)
/*----Working with Array of complex items structure-*/


let arr = [{name: 'Ahmed'}, {name: 'Rami'}, {name: 'Abdennour'}];


arr= new EnhancedArray(...arr);




console.log(
arr.findIndexes((o) => o.name.startsWith('A'))
)

我们可以使用 Stack 并在每次遇到条件“ arr [ i ] = = value”时将“ i”推入堆栈中

看看这个:

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();
}
}

注: MDN 给出的是 使用 while 循环的方法:

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);
}

我不会说这比其他答案好,只是有趣。

更简单的方式与 es6风格。

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); // []

这对我很有效:

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]

我只是想用另一种简单的方法来更新。

还可以使用 forEvery 方法。

var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];


var result = [];


Cars.forEach((car, index) => car === 'Nano' ? result.push(index) : null)

你可以同时使用 mapfilter来编写一个简单易读的解决方案:

const nanoIndexes = Cars
.map((car, i) => car === 'Nano' ? i : -1)
.filter(index => index !== -1);

编辑: 如果你不需要支持 IE/Edge (或者正在翻译你的代码) ,ES2019给了我们 平面地图,它可以让你在一个简单的一行程序中做到这一点:

const nanoIndexes = Cars.flatMap((car, i) => car === 'Nano' ? i : []);

只是为了共享另一种方法,你也可以使用 函数生成器来实现结果:

function findAllIndexOf(target, needle) {
return [].concat(...(function*(){
for (var i = 0; i < target.length; i++) if (target[i] === needle) yield [i];
})());
}


var target = "hellooooo";
var target2 = ['w','o',1,3,'l','o'];


console.log(findAllIndexOf(target, 'o'));
console.log(findAllIndexOf(target2, 'o'));

const indexes = cars
.map((car, i) => car === "Nano" ? i : null)
.filter(i => i !== null)
["a", "b", "a", "b"]
.map((val, index) => ({ val, index }))
.filter(({val, index}) => val === "a")
.map(({val, index}) => index)


=> [0, 2]

你可以使用填充材料

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;
};
}

像这样使用它:

[2,23,1,2,3,4,52,2].filterIndex(element => element === 2)


result: [0, 3, 7]

当两个参数都作为数组传递时


function getIndexes(arr, val) {
var indexes = [], i;
for(i = 0; i < arr.length; i++){
for(j =0; j< val.length; j++) {
if (arr[i] === val[j])
indexes.push(i);
}
}
return indexes;
}