Как рекурсивно отфильтровать элементы многомерного массива?
Функция должна в массив 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 шт):
Вам всего лишь нужно проверять, является ли элемент массива числом или массивом.
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)
Справочный материал, на всякий случай, если что-то будет не понятно:
Можно воспользоваться методом 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);