Как найти индексы всех вхождений элемента в массиве?



Я пытаюсь найти индекс всех экземпляров элемента, скажем, "Nano", в массиве JavaScript.



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


пробовал jQuery.inArray, или аналогично, .indexOf (), но он только дал индекс последнего вхождения элемента, т. е. 5 в этом случае.



Как я могу получить его для всех экземпляров?

1609   7  

7 ответов:

The .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]

N. B.: Регистрация совместимость с браузерами на reduce метод и использовать полифилл если требуется.

другой подход с использованием массив.прототип.map () и массив.прототип.filter ():

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

Примечание: 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 "в стек каждый раз, когда мы сталкиваемся с условием"arr[i]==value"

проверить это:

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

findIndex получает только первый индекс, который соответствует выходу обратного вызова. Вы можете реализовать свой собственный 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'))
)

Если вы собираетесь использовать подчеркивание / lodash, вы можете сделать

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]

Comments

    Ничего не найдено.