JavaScript | Как получить индексы элементов с одинаковыми значениями в массиве?

JavaScript | Как получить индексы элементов с одинаковыми значениями в массиве?

Решение задачи

Array.from(massiv.entries()).filter(i => i[1] == "ТВОЁ_ЗНАЧЕНИЕ_ЭЛЕМЕНТА").map(i => i[0])
// Альтернативный способ
Object.entries(massiv).filter(i => i[1] == "ТВОЁ_ЗНАЧЕНИЕ_ЭЛЕМЕНТА").map(i => Number(i[0]))
Object.entries(massiv).map(i => {if (i[1] == "ТВОЁ_ЗНАЧЕНИЕ_ЭЛЕМЕНТА"){return Number(i[0])}}).filter(i => i != undefined)
"ТВОЁ_ЗНАЧЕНИЕ_ЭЛЕМЕНТА" - в данном случае строка или число. Чтобы сравнивать объекты нужно другое условие.

 

Видео инструкция

В этом видео приводится пример получения индексов элементов массива JavaScript, с одинаковыми значениями. Ввод команд осуществляется в консоль браузера Google Chrome. Результат виден сразу.

Что у нас есть?

Есть массив:

var massiv = ["qw", "qe", "qr", "as", "ad", "af", "zx", "zc", "zv", "qaz", "as", "as"]

Мы хотим получить все индексы элементов из массива massiv, в которых встречается строковое значение «as». Строковое значение повторяется 3 раза. Нам нужно отловить все три положения и вернуть список индексов.

Массив из 12 элементов - JavaScript
Массив из 12 элементов — JavaScript

 

Простой способ — Через итератор массивов

На массиве вызываем метод объекта-прототипа entries():

massiv.entries()
Итератор массива - JavaScript
Итератор массива — JavaScript

В ответ нам прилетает прототип итератора массива.

Итератор массива — это объект, который представляет собой конкретную итерацию над некоторым конкретным объектом экземпляра массива. Для объектов Array Iterator не существует именованного конструктора. Вместо этого объекты итератора массива создаются путем вызова определенных методов объектов экземпляра массива.

Итератор массива имеет всего одно свойство — next().

Если сейчас мы передадим этот итератор массива в метод from() конструктора Array, то в ответ мы получим массив такой же длины, у которого элементами будут массивы с парами «ключ/значение». Причём ключ будет иметь числовой тип данных — это нам и нужно.

Array.from(massiv.entries())
Создание массива из итератора массива - JavaScript
Создание массива из итератора массива — JavaScript

 

Теперь нам нужно отфильтровать данный массив методом объекта-прототипа filter()

Array.from(massiv.entries()).filter(i => i[1] == "as")
Фильтруем массив из итератора - JavaScript
Фильтруем массив из итератора — JavaScript

Вытаскиваем ключи из вложенных массивов методом объектов-прототипов map()

Array.from(massiv.entries()).filter(i => i[1] == "as").map(i => i[0])
Извлечение индексов с одинаковыми элементами as - JavaScript
Извлечение индексов с одинаковыми элементами as — JavaScript

Задача решена. Список получен.

 

Способ №1 — через конструктор Object

Для начала создадим массив средствами конструктора Object, а именно свойством entries().

Object.entries(massiv)

Аргументом функции был наш массив. Эта команда вернёт нам новый массив, в котором элементами будут пары-массивы «ключ/значение» начального массива. Давайте смотреть. Проще один раз увидеть как это будет выглядеть.

Новый массив где элементы - это пары ключ-значение - JavaScript
Новый массив где элементы — это пары ключ-значение — JavaScript

Фильтруем этот массив на наличие строки «as»

Object.entries(massiv).filter(i => i[1] == "as")
Работа фильтра - JavaScript
Работа фильтра — JavaScript

Вытаскиваем значения первого элемента вложенного массива

Object.entries(massiv).filter(i => i[1] == "as").map(i => i[0])
Получение индексов в виде строк
Получение индексов в виде строк

 

Преобразовываем строки в числа

Object.entries(massiv).filter(i => i[1] == "as").map(i => Number(i[0]))
Преобразовываем строки в числа - JavaScript
Преобразовываем строки в числа — JavaScript

Мы получили нужные индексы одинаковых значений в массиве.

 

 

Альтернативный способ — «Замудрёный»

По этому массиву мы можем пробежаться свойством прототипов объекта Arraymap(). На каждой итерации мы будем возвращать первые элементы во из вложенных массивов только в том случае, если будет выполняться условие — второй элемент внутренних массивов должен быть равен искомому значению — «as».

Важный момент! Функция entries() возвращает нам строковые пары массивов. Чтобы не получать строку, в методе map мы будем сразу преобразовывать строковый тип данных в числовой и возвращать его. Будем пользоваться конструктором Number() и передавать в него значение первого элемента вложенного массива.

Object.entries(massiv).map(i => {if (i[1] == "as"){return Number(i[0])}})
Массив из map с undefined c Number - JavaScript
Массив из map с undefined c Number — JavaScript

 

Если без конструктора Number, то вернутся строки. Нам это не подходит.

Массив из map с undefined без Number - JavaScript
Массив из map с undefined без Number — JavaScript

 

Мы уже видим нужные нам индексы. Теперь нужно отфильтровать массив. Мы уберём все элементы со значениями undefined.

Object.entries(massiv).map(i => {if (i[1] == "as"){return Number(i[0])}}).filter(i => i != undefined)
Массив из трёх искомых индексов - JavaScript
Массив из трёх искомых индексов — JavaScript
[3, 10, 11]

Мы получили индексы элементов с одинаковыми значениями в первоначальном массиве. То есть под индексами 3, 10, 11 будут лежать одинаковые значения «as».

Проверяем:

massiv[3]
massiv[10]
massiv[11]
Все три индекса вернули одинаковое значение - JavaScript
Все три индекса вернули одинаковое значение — JavaScript

Всё отлично. Мы решили задачу.

 

Информационные ссылки

Стандарт ECMAScript — Object.entries ( O ) — https://tc39.es/ecma262/#sec-object.entries

Стандарт ECMAScript — Array.prototype.map ( callbackfn [ , thisArg ] ) — https://tc39.es/ecma262/#sec-array.prototype.map

Стандарт ECMAScript — Number ( value ) — https://tc39.es/ecma262/#sec-number-constructor-number-value

Стандарт ECMAScript — Array.prototype.filter ( callbackfn [ , thisArg ] ) — https://tc39.es/ecma262/#sec-array.prototype.filter

 

JavaScript | How do I get the indices of elements with the same values in an array?