Как рекурсивно отфильтровать элементы многомерного массива?

Функция должна в массив arrayTwo добавить рекурсивно только числовые элементы arrayOne.

let arrayOne = [
    8, 2,
    [1, 6, 'm', 4, 't'],
    [[3, 'b'], [7, 'x', [7, 'f', 'l']]],
    22, 5, 'y', 3,
    [[[[['k', 1, [9, 'u', 4]]]]]]
];

let arrayTwo = [];

Так добавляю вообще все элементы (работает):

let i = 0;

function elementFiltering(array) {
    arrayTwo.push(array[i]);
    i++;
    if (i == arrayOne.length) return;
    elementFiltering(array);

    document.querySelector('.out').textContent = arrayTwo;
}

document.querySelector('button').onclick = elementFiltering(arrayOne);

Но не получается отфильтровать, пытался сделать таким способом:

for (let item in array[i]) {
    if (!isNaN(array[i][item])) {
        arrayTwo.push(array[i][item]);
    }
}
i++;
if (i == arrayOne.length) return;
elementFiltering(array);

Тогда пропускаются элементы 8 и 2, первый вложенный массив ( [1, 6, 'm', 4, 't'] ) фильтруется, а дальше ничего не происходит.

Подскажите пожалуйста, как можно решить данную задачу.

UPD

С помощью подсказки от @Neverm1ndo смог упростить код:

let arrayOne = [
    8, 2,
    [1, 6, 'm', 4, 't'],
    [[3, 'b'], [7, 'x', [7, 'f', 'l']]],
    22, 5, 'y', 3,
    [[[[['k', 1, [9, 'u', 4]]]]]]
];

let arrayTwo = [];

function elementFiltering(array) {
    for (let i = 0; i < array.length; i++) {
        if (typeof array[i] == 'number') arrayTwo.push(array[i]);
        if (Array.isArray(array[i])) elementFiltering(array[i]);
    }
    return arrayTwo;
}

elementFiltering(arrayOne);

console.log(arrayTwo);

Ответы (2 шт):

Автор решения: Neverm1ndo

Вам всего лишь нужно проверять, является ли элемент массива числом или массивом.

let arrayOne = [
    8, 2,
    [1, 6, 'm', 4, 't'],
    [[3, 'b'], [7, 'x', [7, 'f', 'l']]],
    22, 5, 'y', 3,
    [[[[['k', 1, [9, 'u', 4]]]]]]
];

let arrayTwo = [];

function elementFiltering(array) {
  const result = [];
  for(let i = 0; i < array.length; i++) {
    if (typeof array[i] == 'number') { // проверка на число
      result.push(array[i]);
      continue; // идем дальше
    }
    if (!Array.isArray(array[i])) continue; // если элемент - не массив, идем дальше
    result.push(...elementFiltering(array[i])); // оператор ... (spread) как бы разбирает массив, которого нам вернул elementFiltering на аргументы
  }
  return result;
}

arrayTwo.push(...elementFiltering(arrayOne));

console.log(arrayTwo);

UPD

Вариант, если нужно просто вызвать функцию elementFiltering

let arrayOne = [
    8, 2,
    [1, 6, 'm', 4, 't'],
    [[3, 'b'], [7, 'x', [7, 'f', 'l']]],
    22, 5, 'y', 3,
    [[[[['k', 1, [9, 'u', 4]]]]]]
];

let arrayTwo = [];

function elementFiltering(array) {
  const result = [];
  for(let i = 0; i < array.length; i++) {
    if (typeof array[i] == 'number') { // Если элемент число
      arrayTwo.push(array[i]);
      continue;
    }
    if (!Array.isArray(array[i])) continue; // Если элемент не массив, идем дальше
    result.push(...elementFiltering(array[i])); //
  }
  return result;
}

elementFiltering(arrayOne);

console.log(arrayTwo)

Справочный материал, на всякий случай, если что-то будет не понятно:

→ Ссылка
Автор решения: EzioMercer

Можно воспользоваться методом Array.prototype.reduce(), который перебирает массив и может сразу записывать значение в нужном виде без объявления лишних переменных

Ну логика предельна проста:

  • Если число, то добавляем в результат
  • Если нет и это массив, то запускаем для него этот же алгоритм и элементы нового результата записываем в предыдущий результат

Код:

const arrayOne = [
    8, 2,
    [1, 6, 'm', 4, 't'],
    [[3, 'b'], [7, 'x', [7, 'f', 'l']]],
    22, 5, 'y', 3,
    [[[[['k', 1, [9, 'u', 4]]]]]]
];

const getAllNums = (arr) => {
  return arr.reduce((result, el) => {
    if (typeof el === 'number') result.push(el);
    else if (Array.isArray(el)) result.push(...getAllNums(el));
    
    return result;
  }, []);
}

const arrayTwo = getAllNums(arrayOne);

console.log(arrayTwo);

Если нужен будет вариант без рекурсии (т.е. самому не реализовывать рекурсию), то можно так:

  • С помощью Array.prototype.flat() (сам метод рекурсивный) преобразуем многомерный массив в одномерный
  • Из получившегося массива оставлем только те, у кого тип - это число

Код:

const arrayOne = [
    8, 2,
    [1, 6, 'm', 4, 't'],
    [[3, 'b'], [7, 'x', [7, 'f', 'l']]],
    22, 5, 'y', 3,
    [[[[['k', 1, [9, 'u', 4]]]]]]
];

const arrayTwo = arrayOne.flat(Infinity).filter(x => typeof x === 'number');

console.log(arrayTwo);

→ Ссылка