4.2. Демонстрация - Уменьшение вложенности массива

Шаг 1

Посмотрим на следующую довольно прикладную задачу. У нас есть массив с элементами и другими массивами — вложенность может быть любой. Нужно устранить вложенность, сохранив очерёдность элементов. Легче всего понять эту задачу, просто посмотрев на примеры. Попробуйте самостоятельно решить эту задачу с помощью рекурсии! P. S. Сейчас эту задачу решает встроенный Array.prototype.flat, но раньше его не было.


import {test} from "./tester";

/*
Примеры:
flat([]) // []
flat([[1, 5], 5, 10]) // [1, 5, 5, 10]
flat([1, 2, [3, 4]]) // [1, 2, 3, 4]
flat([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
*/

function flat(array) {
  return [];
}

test(flat([]), []);
test(flat([[1, 5], 5, 10]), [1, 5, 5, 10]);
test(flat([1, 2, [3, 4]]), [1, 2, 3, 4]);
test(flat([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

Шаг 2

Начнём с простого: предположим, что у нас все элементы — это не массивы. Тогда каждый случай будет для нас базовым, просто итеративно переложим один массив в другой.


import {test} from "./tester";

/*
Примеры:
flat([]) // []
flat([[1, 5], 5, 10]) // [1, 5, 5, 10]
flat([1, 2, [3, 4]]) // [1, 2, 3, 4]
flat([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
*/

function flat(array) {
  const result = [];

  for (const element of array) {
    result.push(element);
  }

  return result;
}

test(flat([]), []);
test(flat([[1, 5], 5, 10]), [1, 5, 5, 10]);
test(flat([1, 2, [3, 4]]), [1, 2, 3, 4]);
test(flat([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

Шаг 3

А теперь введём рекурсивный случай. Если встречаем массив, то будем вызывать flat уже на нём. Этот случай будет приближать нас к базовому — рано или поздно вложенность закончится, и мы встретим «простые» элементы.


import {test} from "./tester";

/*
Примеры:
flat([]) // []
flat([[1, 5], 5, 10]) // [1, 5, 5, 10]
flat([1, 2, [3, 4]]) // [1, 2, 3, 4]
flat([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
*/

function flat(array) {
  const result = [];

  for (const element of array) {
    if (Array.isArray(element)) {
      result.push(...flat(element))
    } else {
      result.push(element);
    }
  }

  return result;
}

test(flat([]), []);
test(flat([[1, 5], 5, 10]), [1, 5, 5, 10]);
test(flat([1, 2, [3, 4]]), [1, 2, 3, 4]);
test(flat([1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

File tester.js


const results = document.getElementById('results')

export function test(rawLeft, rawRight) {
  const result = document.createElement('li');

  // Небольшой хак для сравнения массивов. Не делайте так в production!
  const left = JSON.stringify(rawLeft);
  const right = JSON.stringify(rawRight);

  if (left === right) {
    result.innerHTML = "Тест пройден!";
    result.style.color = "green";
  } else {
    result.innerHTML = `Тест не пройден! ${left} не равно ${right}`;
    result.style.color = "red";
  }

  results.appendChild(result);
}