简体   繁体   English

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

[英]How to find the indexes of all occurrences of an element in array?

I am trying to find the indexes of all the instances of an element, say, "Nano", in a JavaScript array.我正在尝试在 JavaScript 数组中查找元素(例如“Nano”)的所有实例的索引。

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, ie 5 in this case.我尝试了 jQuery.inArray或类似的.indexOf() ,但它只给出了元素最后一个实例的索引,即在本例中为 5。

How do I get it for all instances?我如何为所有实例获取它?

The .indexOf() method has an optional second parameter that specifies the index to start searching from, so you can call it in a loop to find all instances of a particular value: .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");

You don't really make it clear how you want to use the indexes, so my function returns them as an array (or returns an empty array if the value isn't found), but you could do something else with the individual index values inside the loop.您并没有真正明确您想如何使用索引,所以我的函数将它们作为数组返回(如果找不到值,则返回一个空数组),但是您可以对各个索引值执行其他操作循环内。

UPDATE: As per VisioN's comment, a simple for loop would get the same job done more efficiently, and it is easier to understand and therefore easier to maintain:更新:根据 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;
}

Another alternative solution is to use Array.prototype.reduce() :另一种替代解决方案是使用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]

NB: Check the browser compatibility for reduce method and use polyfill if required.注意:检查reduce方法的浏览器兼容性,并在需要时使用polyfill

另一种使用Array.prototype.map()Array.prototype.filter() 的方法

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

More simple way with es6 style. 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); // []

You can write a simple readable solution to this by using both map and filter :您可以使用mapfilter编写一个简单易读的解决方案:

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:编辑:如果您不需要支持 IE/Edge(或正在转译您的代码),ES2019 为我们提供了flatMap ,它可以让您以简单的单行方式执行此操作:

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

I just want to update with another easy method.我只想用另一种简单的方法进行更新。

You can also use forEach method.您也可以使用 forEach 方法。

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

var result = [];

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

Note: MDN gives a method using a while loop :注意: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);
}

I wouldn't say it's any better than other answers.我不会说它比其他答案更好。 Just interesting.只是有趣。

const indexes = cars
    .map((car, i) => car === "Nano" ? i : null)
    .filter(i => i !== null)

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]

Just to share another method, you can use Function Generators to achieve the result as well:只是分享另一种方法,您也可以使用函数生成器来实现结果:

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

["a", "b", "a", "b"]
   .map((val, index) => ({ val, index }))
   .filter(({val, index}) => val === "a")
   .map(({val, index}) => index)

=> [0, 2]

You can use Polyfill您可以使用 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]

findIndex retrieves only the first index which matches callback output. findIndex仅检索与回调输出匹配的第一个索引。 You can implement your own findIndexes by extending Array , then casting your arrays to the new structure .您可以通过扩展 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')) )

We can use Stack and push "i" into the stack every time we encounter the condition "arr[i]==value"每次遇到条件“arr[i]==value”时,我们可以使用Stack并将“i”压入堆栈

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

When both parameter passed as array当两个参数都作为数组传递时


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

Also, findIndex() will be useful:此外, findIndex()将很有用:

var cars = ['Nano', 'Volvo', 'BMW', 'Nano', 'VW', 'Nano'];

const indexes = [];
const searchedItem = 'NaNo';

cars.findIndex((value, index) => {
  if (value.toLowerCase() === searchedItem.toLowerCase()) {
    indexes.push(index);
  }
});

console.log(indexes); //[ 0, 3, 5 ]

Bonus:奖金:

This custom solution using Object.entries() and forEach()此自定义解决方案使用Object.entries()forEach()

var cars = ['Nano', 'Volvo', 'BMW', 'Nano', 'VW', 'Nano'];

const indexes = [];
const searchableItem = 'Nano';

Object.entries(cars).forEach((item, index) => {
  if (item[1].toLowerCase() === searchableItem.toLowerCase())
    indexes.push(index);
});

console.log(indexes);

Note: I did not run run all tests注意:我没有运行运行所有测试

If you intend to use underscore/lodash, you could do 如果您打算使用下划线/破折号,则可以

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

_.chain(Cars).map((v, i)=> [i, v === "Nano"]).filter(v=>v[1]).map(v=>v[0]).value()

[0, 3, 5]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM