Как найти индексы всех вхождений элемента в массиве?
Я пытаюсь найти индекс всех экземпляров элемента, скажем, "Nano", в массиве JavaScript.
var Cars = ["Nano", "Volvo", "BMW", "Nano", "VW", "Nano"];
пробовал jQuery.inArray, или аналогично, .indexOf (), но он только дал индекс последнего вхождения элемента, т. е. 5 в этом случае.
Как я могу получить его для всех экземпляров?
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