1. Разница между Array.prototype.flatMap и Array.prototype.flat
  2. Практические примеры использования Array.prototype.flatMap
  3. Практические примеры использования Array.prototype.map
  4. Как реализовать Array.prototype.flatMap
  5. Как реализовать Array.prototype.flatMap

Разница между Array.prototype.flatMap и Array.prototype.flat

Array.prototype.flat — это метод, позволяющий сглаживать вложенные массивы до определенного уровня глубины. По умолчанию он сгладит один уровень:

const nestedNumbers = [1, [2, 3], [4, [5, 6]]];

const flatResult = nestedNumbers.flat();
console.log(flatResult); // [1, 2, 3, 4, [5, 6]]

В этом случае flat сглаживает массив только на один уровень. Если вам нужно сгладить до более глубоких уровней, вы можете указать аргумент глубины:

const resultFlatDeep = nestedNumbers.flat(2);
console.log(resultFlatDeep); // [1, 2, 3, 4, 5, 6]

С другой стороны, Array.prototype.flatMap представляет собой комбинацию карты и плоскости. Он применяет функцию сопоставления к каждому элементу массива, а затем сводит результат в новый массив, но сглаживает только на один уровень в глубину. Давайте посмотрим на пример:

const numbers = [1, 2, 3, 4];
const result = numbers.numbers(numero => [numero, numero * 2]);
console.log(result); // [1, 2, 2, 4, 3, 6, 4, 8]

Таким образом, Array.prototype.flat — это метод, используемый для выравнивания вложенных массивов до определенного уровня глубины, в то время как Array.prototype.flatMap сочетает отображение и выравнивание массива в одной операции, облегчая преобразование и выравнивание массивов в определенные случаи.

Практические примеры использования Array.prototype.flatMap

Пример 1: Извлечение свойств объектов в массиве

Предположим, у вас есть массив объектов, представляющих людей и их друзей, и вы хотите извлечь все имена в один массив:

const persons = [
  {
    name: 'Ana',
    friends: [{ name: 'Charles' }, { name: 'Sophie' }]
  },
  {
    name: 'Peter',
    friends: [{ name: 'Maria' }, { name: 'John' }]
  }
];

const names = persons.flatMap(person => [
  person.name,
  ...person.friends.map(friend => friend.name)
]);

console.log(names); // ['Ana', 'Charles', 'Sophie', 'Peter', 'Maria', 'John']

Пример 2. Фильтрация и преобразование значений в массиве

Представьте, что у вас есть массив чисел, и вы хотите получить новый массив, содержащий только повторяющиеся четные числа:

const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]
const evenNumbersDuplicates = numeros.flatMap(number =>
  number % 2 === 0 ? [number * 2] : []
);

console.log(evenNumbersDuplicates); // [4, 8, 12, 16]

Пример 3: Объединение элементов массива в двумерный массив

Учтите, что у вас есть два массива одинаковой длины, и вы хотите объединить элементы обоих массивов в новый двумерный массив:

const array1 = ['a', 'b', 'c'];
const array2 = [1, 2, 3];
const combined = array1.flatMap((element, index) => [
  [element, array2[index]]
]);

console.log(combined); // [['a', 1], ['b', 2], ['c', 3]]

Ejemplos prácticos del uso de Array.prototype.flat

Пример 1. Сведение вложенных массивов

Представьте, что у вас есть двумерный массив чисел, и вы хотите преобразовать его в одномерный массив:

const array = [  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

const flattened = array.flat();

console.log(flattened); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

Пример 2: Объединение нескольких массивов в один

Предположим, у вас есть массив, содержащий несколько массивов слов, и вы хотите объединить их в один массив:

const wordsGrouped = [
  ['apple', 'banana', 'cherry'],
  ['dog', 'cat', 'elephant'],
  ['sun', 'moon', 'star']
];

const words = wordsGrouped.flat();

console.log(words); // ['apple', 'banana', 'cherry', 'dog', 'cat', 'elephant', 'sun', 'moon', 'star'.]

Пример 3: Удаление пустых элементов в массиве

Учтите, что у вас есть массив с пустыми элементами, и вы хотите их удалить:

const withEmptyElements = [1, , 2, , 3, 4, , 5];
const withoutEmptyElements = withEmptyElements.flat();

console.log(withoutEmptyElements); // [1, 2, 3, 4, 5]

Стоит отметить, что в этом случае flat удаляет пустые элементы только потому, что они находятся на уровне вложенности.

Как реализовать Array.prototype.flatMap

Если вы используете версию JavaScript до ES12 и у вас нет доступа к Array.prototype.flatMap, вы можете реализовать свою собственную версию, используя Array.prototype.reduce и Array.prototype.concat. Вот пример того, как это сделать:

if (!Array.prototype.flatMap) {
  Array.prototype.flatMap = function (callback, thisArg) {
    if (this == null) {
      throw new TypeError(
        "Array.prototype.flatMap called on null or undefined"
      );
    }
    if (typeof callback !== "function") {
      throw new TypeError(callback + " is not a function");
    }
    const array = Object(this);
    const len = array.length >>> 0;
    const newArray = [];
    for (let i = 0; i < len; i++) {
      if (i in array) {
        const mappedValue = callback.call(thisArg, array[i], i, array);
        newArray.push(...mappedValue);
      }
    }
    return newArray;
  };
}

Эта реализация использует reduce и concat для применения функции сопоставления и сведения результата в новый массив. Реализация также проверяет, имеет ли это значение null или undefined и является ли обратный вызов функцией, что необходимо для обеспечения согласованности с поведением Array.prototype.flatMap в ES12.
После включения этого кода в ваш проект вы можете использовать flatMap так же, как и нативную версию:

const numbers = [1, 2, 3, 4];
const result = numbers.flatMap(number => [number, number * 2]);

console.log(result); // [1, 2, 2, 4, 3, 6, 4, 8]

Обратите внимание, что хотя эта реализация работает в большинстве случаев, могут быть небольшие отличия от поведения Array.prototype.flatMap в ES12. Всегда рекомендуется обновляться до последней версии JavaScript, когда это возможно, чтобы воспользоваться собственными функциями и улучшениями производительности.

Как реализовать Array.prototype.flat

Если вы используете версию JavaScript до ES12 и у вас нет доступа к Array.prototype.flat, вы можете реализовать свою собственную версию, используя Array.prototype.reduce и Array.prototype.concat. Вот пример того, как это сделать:

if (!Array.prototype.flat) {
  Array.prototype.flat = function (depth = 1) {
    if (this == null) {
      throw new TypeError("Array.prototype.flat called on null or undefined");
    }

    if (depth < 0) {
      return this.slice(); // Returns a copy of the original array if the depth is negative
    }

    const flattenArray = (arr, currentDepth) => {
      if (currentDepth === depth) {
        return arr.slice();
      }
      return arr.reduce((acc, item) => {
        if (Array.isArray(item)) {
          acc.push(...flattenArray(item, currentDepth + 1));
        } else {
          acc.push(item);
        }
        return acc;
      }, []);
    };
    return flattenArray(this, 0);
  };
}

В этой реализации используется reduce and concat для рекурсивного выравнивания массива. Функция flattenArray вызывается рекурсивно в соответствии с глубиной, указанной в аргументе depth. Реализация также проверяет, является ли это значением null или undefined, что необходимо для обеспечения согласованности с поведением Array.prototype.flat в ES12.
После включения этого кода в свой проект вы можете использовать flat так, как хотели бы. родная версия:

const nestedNumbers = [1, [2, 3], [4, [5, 6]]];
const resultFlat = nestedNumbers.flat();

console.log(resultFlat); // [1, 2, 3, 4, [5, 6]]

Обратите внимание, что хотя эта реализация работает в большинстве случаев, могут быть небольшие отличия от поведения Array.prototype.flat в ES12. Всегда рекомендуется обновляться до последней версии JavaScript, когда это возможно, чтобы воспользоваться собственными функциями и улучшениями производительности.

Хулио Лейва Диас 👨🏻💻 FrontEnd Software Engineer

Информационный бюллетень | Гитхаб