@toha_man

Какой метод перебора массивов JS использовать и как?

Имеется массив от 0 ... 100 заполненный рандомным образом нулями и единицами.
Задача: используя методы перебора массивов из JS (reduce, map, filter) и не используя второго массива получить
массив который бы содержал в себе индексы элементов с единицами.

Пример.
Пусть исходный массив arr = [0, 1, 1, 0, 0, 0, 1]
Тогда result = [ 1, 2, 6] - индексы единиц.

Метод filter возвращает значение элементов для которых callback true,
метод map при каждом вызове обязательно что-то возвращает (undefined при элементе с 0)

Если через forEach то нужен второй массив, так работает, но интересно решить без него. Спасибо
  • Вопрос задан
  • 1289 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
map/filter:

arr.map((n, i) => n ? i : null).filter(n => n !== null)
// или
arr.map((n, i) => n ? i : NaN).filter(n => n === n)
// или
arr.map((n, i) => !!n && i).filter(Number.isInteger)
// или
arr.map((n, i) => !n || i).filter(n => n !== !0)

reduce:

arr.reduce((acc, n, i) => n ? [ ...acc, i ] : acc, [])
// или
arr.reduce((acc, n, i) => (n && acc.push(i), acc), [])

или, если надо изменить текущий массив, а не создавать новый

for (let i = arr.length; i--; ) {
  if (arr[i]) {
    arr[i] = i;
  } else {
    arr.splice(i, 1);
  }
}

// или

arr.reduceRight((_, n, i, a) => n ? a[i] = i : a.splice(i, 1), 0);

// или

let count0 = 0;

arr.forEach((n, i, a) => {
  a[i - count0] = i;
  count0 += !n;
});

arr.length -= count0;
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 5
ignat_one
@ignat_one
web-developer
Например, так: (не успел чуть-чуть, решение такое же, как у 0xD34F )

let result = arr.map( (item, index) => { return item === 1 ? index : 0 }).filter( item => { return item !== 0});
Ответ написан
Комментировать
@RidgeA
Открою секрет - в цепочке с map и filter будет использовано 2 дополнительных массива и 2 прохода по массиву.
Можно использовать reduce и добавлять нужные элементы в аккамулирующий массив (будет 1 новый массив) за 1 проход.
Ответ написан
Комментировать
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Самое нормальное решение — через reduce, он для этого и существует. Но там технически есть второй массив.
arr.reduce((arr, n, i) => {
  if (n === 1) {
    arr.push(i);
  }

  return arr;
}, []);


Если использовать цепочку map + filter, там тоже, технически, используется промежуточный массив.

В чем смысл вашей задачи? Или это теоретическое упражнение?
Ответ написан
@toha_man Автор вопроса
Всем огромное спасибо за ответы. Очень понравились ответы. Впитал капельку опыта и знаний)

Я не совсем точно сформулировал вопрос. Моё решение изначально было в использовании 2х массивов таким образом -
var primes = [], arr = []  ;

primes.forEach( (el, i) => el > 0 ? arr.push(i) : 0 )

И мне было интересно как исключить использование arr, поэтому все ваши ответы мне подошли.

А вот по скорости получается что вариант с reduce работает крайне долго. Как думаете почему ? Из-за частой раскладки массива [...acc] ? Это все в случае с большим исходным массивом > 10 000 000 элементов

Вот такой у меня результат по времени получается:
reduce - prntscr. com/kjbdzz
.map().filter - prntscr. com/kjbkc6
.forEach - prntscr. com/kjbksw
Ответ написан
bubandos
@bubandos
bash'у, javascript'ую, php'лю, css'аю, html'каю
Второй массив будет всегда, как ни крути, хотя бы потому, что на выходе вы хотите получить массив.
Если хотите без второго массива - складывайте результат, например, в строку через разделитель.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
29 мар. 2024, в 17:14
4000 руб./за проект
29 мар. 2024, в 17:04
5000 руб./за проект
29 мар. 2024, в 17:03
3000 руб./за проект