Форум программистов, компьютерный форум, киберфорум
JavaScript
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
8 / 8 / 5
Регистрация: 08.10.2012
Сообщений: 248
1

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

26.01.2018, 00:18. Просмотров 1164. Ответов 11
Метки нет (Все метки)

Дано:

HTML5
1
2
3
dateId[0] = 1;
dateId[1] = 16;
dateId[2] = 5;
или dateId["1","16","5"]

Как получить x. где dateId[x] равна 5?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.01.2018, 00:18
Ответы с готовыми решениями:

Найти индекс элемента массива по его значению
Здравствуйте. For Each de As String In arr 'de - переменная типа String, равна...

Как получить индекс элемента массива files по его имени
Вопрос в теме.

Как получить индекс по значению map
std::map<string, string> m {{"123", "shit"}, {"321", "govno"}, {"234", "curva"}}; return...

Как получить индекс структуры по значению поля
Здравствуйте, нужно удалить или изменить значение записи структуры, но сначала найти удаляемую...

11
Эксперт PHP
931 / 689 / 235
Регистрация: 01.02.2015
Сообщений: 1,848
26.01.2018, 00:33 2
Javascript
1
console.log([1, 16, 5].findIndex(e=>e===5));
или циклом по массиву пробежитесь сравнивая с значением если равно то break, return ...
1
704 / 306 / 190
Регистрация: 05.03.2015
Сообщений: 822
26.01.2018, 01:11 3
Если нужен первый найденный индекс, то подойдет вариант автора выше, в противном случае все индексы можно найти так:

Javascript
1
2
3
4
5
6
7
var a = [1,5,6,5,1];
 
var indexes = a.reduce((result, el, index) => {
    return el === 5 ? result.concat(index) : result
},[]);
 
console.log(indexes)
2
536 / 439 / 176
Регистрация: 14.10.2017
Сообщений: 1,205
26.01.2018, 01:52 4
msheal, можно ведь убрать return и фигурные скобки?
1
704 / 306 / 190
Регистрация: 05.03.2015
Сообщений: 822
26.01.2018, 02:27 5
klopp, разумеется) Мне показалось что так будет читабельней - не все еще привыкли к сокращенным записям и стрелочным функциям)
2
536 / 439 / 176
Регистрация: 14.10.2017
Сообщений: 1,205
26.01.2018, 02:38 6
msheal, а вот если решить эту же задачку таким способом:
Javascript
1
let indexes = a.map((el,i) => el === 5 ? i : undefined).filter(x => x);
то,новый массив,создающийся после выполнения a.map((el,i) => el === 5 ? i : undefined) и имеющий вид [undefined, 1, undefined, 3, undefined] ,он уничтожается после применения к нему filter(x => x)? Меня интересует потребление памяти,при большом размере исходного массива наверное будет подтормаживать по сравнению с вашим способом.
1
704 / 306 / 190
Регистрация: 05.03.2015
Сообщений: 822
26.01.2018, 03:55 7
klopp, предложенный вами способ разумеется хуже по производительности хотя бы за счет того, что вы делаете 2 итерации по всему исходному массиву (итерация по массиву после map тоже считается, длина массива ведь не изменилась). Собственно reduce и создан для такого кумулятивного прохода по массиву с сохранением промежуточного результата. Думаю, можно придумать еще несколько решений типа того, что вы предложили выше, но по скорости и читабельности reduce всяко будет лучше

Добавлено через 28 минут
klopp, малость заморочился и измерил скорость выполнения обоих вариантов.

Результат меня сильно удивил - при небольшом исходном массиве редьюс быстрее, но чем исходный массив больше, тем быстрее ваш вариант. Можете поиграться в консоли сами:


Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var length = 100000;
var a = Array.from({length: length}, () => Math.floor(Math.random() * 10));
 
console.time('reduce');
var b = a.reduce((result, el, index) => {
    return el === 5 ? result.concat(index) : result
},[]);
 
console.timeEnd('reduce')
 
console.time('map + filter');
var c = a.map((el,i) => el === 5 ? i : undefined).filter(x => x);
 
console.timeEnd('map + filter')
UPD: Заменив в редьюсе result.concat(index) на [...result, index] скорость падает почти в 2 раза

Добавлено через 30 минут
UPD2: проверим попутно время выполнения самого "нативного" прохода по массиву.
Javascript
1
2
3
4
5
6
7
8
console.time('for loop');
var d = [];
for (var i = 0; i < length; i++){
    if (a[i] === 5){
        d.push(i)
    }
}
console.timeEnd('for loop');
При с массивом из 100 000 рандомных элементов от 0 до 9 у меня получились результаты которые говорят сами за себя (цифры могут отличаться в разных браузерах):

reduce: 542.385009765625ms
map + filter: 19.831787109375ms
for loop: 2.487060546875ms

Вывод очевиден - критические места пишем исключительно с помощью "старых" методов, жертвуя читабельностью, в обратных ситуциях вполне можно использовать современные методы.
3
536 / 439 / 176
Регистрация: 14.10.2017
Сообщений: 1,205
26.01.2018, 04:50 8
msheal, Я вам больше скажу-установил в вашем коде length в один миллион. Страница зависла,через минуту появилось модальное окно "Страница не отвечает.Желаете подождать?".Закрыл страницу.
Тогда я закомментил блок кода с reduce. Всё быстренько сработало, map + filter: 529ms
Решил всё-таки добить reduce.Теперь закомментил блок кода с map-filter.
Чуть больше чем через 2 мин выдал reduce: 129249.22192382812ms
Разница в 244 раза!

Добавлено через 4 минуты
Предполагаю что вычисление промежуточного результата на каждой итерации более ресурсоёмкая вещь чем просто копирование элемента в новый массив. (Хотя,чушь, промежуточный по идее вычисляется только при выполнении условия, иначе он тоже просто копируется)

Добавлено через 8 минут
Увеличил диапазон рандомных чисел до 100.
reduce: 1315ms
map + filter: 535ms
Т.е. получается reduce замедляет код при большом количестве a[i] === 5, тогда добавление промежуточного результата в результирующий массив влияет на скорость,т.к. при этом увеличивается размер массива,а следовательно происходит обращение к ОС за выделением еще памяти,и,возможно, перезаписывание результирующего массива.

Добавлено через 10 минут
Сделал Math.floor(Math.random() * 1000), и length также миллион:
reduce: 52ms
map + filter: 532.000244140625ms
Очевидно,что количество элементов со значением 5 резко уменьшилось, и скорость reduce резко выросла.
Т.е. тормозил не сам метод reduce, а вот эта часть result.concat(index).

ИМХО,конечно.

Добавлено через 11 минут
Хм,хотя в цикле for точно так же происходит наращивание результирующего массива,а со скоростью всё в порядке даже при Math.floor(Math.random() * 10):
for loop: 18.999755859375ms

Добавлено через 46 секунд
Чето я запутался)))
2
the hardway first
Эксперт JS
1873 / 1403 / 722
Регистрация: 05.06.2015
Сообщений: 2,970
26.01.2018, 09:08 9
Цитата Сообщение от klopp Посмотреть сообщение
а вот эта часть result.concat(index)
Меня тоже смутила эта часть. Зачем каждый раз создавать новый массив?
Javascript
1
2
3
4
var indexes = array.reduce((result, el, index) => {
  if (el === 5) result.push(index);
  return result;
}, []);
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var SIZE = 100000,
  array = [];
 
for (var i = 0; i < SIZE; i++) {
  array.push(Math.round(Math.random() * 10));
}
 
console.time('reduce w/ concat');
array.reduce((result, el, index) => {
  return el === 5 ? result.concat(index) : result;
}, []);
console.timeEnd('reduce w/ concat'); //=> 628.63720703125ms
 
console.time('reduce w/ push');
var indexes = array.reduce((result, el, index) => {
  if (el === 5) result.push(index);
  return result;
}, []);
console.timeEnd('reduce w/ push'); //=> 3.182861328125ms
 
console.time('for w/ push');
var d = [];
for (var i = 0; i < array.length; i++) {
  if (array[i] === 5) d.push(i);
}
console.timeEnd('for w/ push'); //=> 2.609130859375ms
 
console.time('map & filter');
array.map((el, i) => el === 5 ? i : undefined).filter(x => x);
console.timeEnd('map & filter'); //=> 21.31884765625ms
https://jsfiddle.net/j2FunOnly/u2msnb33/

https://jsperf.com/array-iterations-compare/1

Добавлено через 13 минут
klopp, у вас, кстати, баг: если искомый элемент будет первым (а индексы как мы знаем начинаются с 0), то мы потеряем этот индекс такой фильтрацией. Но это не точно.
2
536 / 439 / 176
Регистрация: 14.10.2017
Сообщений: 1,205
26.01.2018, 09:43 10
j2FunOnly, У меня вот еще вопрос, попробовал ваш способ сделать через тернарный оператор,выдает ошибку result.push is not a function
Javascript
1
let b = a.reduce((result, el, index) => el === 5 ? result.push(index) : result,[]);
Вроде бы в коде всё тоже самое по смыслу,а не проходит.
Такой же код,но с concat вместо push ошибки не вызывает.
1
the hardway first
Эксперт JS
1873 / 1403 / 722
Регистрация: 05.06.2015
Сообщений: 2,970
26.01.2018, 09:56 11
klopp, потому что array.push() возвращает размер получившегося массива, но не сам массив. Следовательно после первого же совпадения в result будет 1, а не массив.
2
536 / 439 / 176
Регистрация: 14.10.2017
Сообщений: 1,205
26.01.2018, 16:14 12
j2FunOnly, Благодарю.Вот затупил)))Всегда ведь надо проверять возвращаемое значение.

Цитата Сообщение от j2FunOnly Посмотреть сообщение
у вас, кстати, баг
да,вы правы,не проходит нулевой элемент со значением 5
исправленный вариант:
Javascript
1
let indexes = a.map((el,i) => el === 5 ? i : undefined).filter(x => x != undefined);
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.01.2018, 16:14

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Сортировать массив элементов по присвоенному значению!
Ребят пишу програмку не большую столкнулся с проблеммой! Нужно отсортировать массив не мо индексу...

Вещественная переменная не равна присвоенному значению
Есть такой код: var x: real; begin x:=0.3; if x&lt;&gt;0.3 then writeln('Things going wrong...');...

как определить индекс массива при поиске по значению?
B - массив А - значение B.contains(a) определяю было вхождение или нет, а каким образом...

Получить индекс по значению в ListBox
Всем привет! Как реализовать поиск строки (индекса её), с нужным нам текстом, не зная её индекса.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.