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

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

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

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

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

69 голосов | спросил norbdum 27 FriEurope/Moscow2013-12-27T13:52:40+04:00Europe/Moscow12bEurope/MoscowFri, 27 Dec 2013 13:52:40 +0400 2013, 13:52:40

8 ответов


0

.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;
}
ответил nnnnnn 27 FriEurope/Moscow2013-12-27T13:59:08+04:00Europe/Moscow12bEurope/MoscowFri, 27 Dec 2013 13:59:08 +0400 2013, 13:59:08
0

Другое альтернативное решение - использовать 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 и использование polyfill , если требуется.

ответил VisioN 27 FriEurope/Moscow2013-12-27T14:10:19+04:00Europe/Moscow12bEurope/MoscowFri, 27 Dec 2013 14:10:19 +0400 2013, 14:10:19
0

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

var indices = array.map((e, i) => e === value ? i : '').filter(String)
ответил yckart 21 WedEurope/Moscow2016-12-21T23:41:20+03:00Europe/Moscow12bEurope/MoscowWed, 21 Dec 2016 23:41:20 +0300 2016, 23:41:20
0

Примечание. 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);
}

Я бы не сказал, что это лучше, чем другие ответы. Просто интересно.

ответил abalter 16 Maypm18 2018, 20:53:48
0

Более простой способ в стиле 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); // []
ответил Alex Petre 25 +03002018-10-25T11:20:52+03:00312018bEurope/MoscowThu, 25 Oct 2018 11:20:52 +0300 2018, 11:20:52
0

Мы можем использовать стек и вставлять «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(); 
    }
}
ответил S Banzal 27 MaramTue, 27 Mar 2018 07:29:57 +03002018-03-27T07:29:57+03:0007 2018, 07:29:57
0

findIndex извлекает только первый индекс, который соответствует выводу обратного вызова. Вы можете реализовать свой собственный findIndexes, расширив Array, а затем приведя ваши массивы к новой структуре.

 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'))
)
ответил Abdennour TOUMI 12 AM00000050000004731 2017, 05:32:47
0

Если вы намереваетесь использовать подчеркивание /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]
ответил Zero 16 SatEurope/Moscow2017-12-16T23:02:49+03:00Europe/Moscow12bEurope/MoscowSat, 16 Dec 2017 23:02:49 +0300 2017, 23:02:49

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132