DevGang
Авторизоваться

Изучаем Object.groupBy() и Map.groupBy() в JavaScript

В JavaScript наконец-то появился метод группировки массивов, что означает, что нам не нужно полагаться на lodash, чтобы иметь возможность группировать наши объекты по какому-то ключу. Он уже находится на третьем этапе процесса подачи предложений по ECMAScript, что означает, что очень скоро он появится в Node.js и других браузерах. Хотя он уже есть в Chrome 117. В этом уроке давайте посмотрим, как он работает.

Как мы обычно группируем элементы в JavaScript

Допустим, у нас есть набор фруктов (fruits), и мы хотим сгруппировать объекты по калорийности (calories). Мы могли бы использовать цикл forEach следующим образом:

const fruits = [
  { name: "Banana", calories: 28 },
  { name: "Apple", calories: 30 },
  { name: "Avacado", calories: 28 },
];
 
const fruitByCalories = {};
 
fruits.forEach((fruit) => {
  const calories = fruit.calories;
  if (!fruitByCalories[calories]) {
    fruitByCalories[calories] = [];
  }
  fruitByCalories[calories].push(fruit);
});
console.log(JSON.stringify(fruitByCalories, null, 2));

или мы можем уменьшить его следующим образом:

const fruits = [
  { name: "Banana", calories: 28 },
  { name: "Apple", calories: 30 },
  { name: "Avocado", calories: 28 },
];
const fruitsByCalories = fruits.reduce((acc, fruit) => {
  const calories = fruit.calories;
  if (!acc[calories]) {
    acc[calories] = [];
  }
  acc[calories].push(fruit);
  return acc;
}, {});
console.log(JSON.stringify(fruitsByCalories, null, 2));

Выход:

Для обоих приведенных выше кодов вывод будет следующим:

В любом случае код довольно неуклюжий. Вы всегда должны проверять объект, чтобы увидеть, существует ли ключ группировки, а если нет, создавать его, используя пустой массив. Затем вы можете поместить элемент в массив.

Группировка элементов в JS с помощью groupBy()

К счастью, теперь у нас есть новые методы, которые работают с объектами и картами. Эти методы можно использовать для группировки объектов или сопоставления данных.

Object.groupBy()

Object.groupBy принимает элементы, которые должны быть итерируемыми, например массив, и функцию обратного вызова, аналогичную другим методам. Обратный вызов получает элемент, в котором в данный момент находится итерируемый объект, и, при необходимости, индекс, если вы хотите его использовать. Вы можете использовать его следующим образом:

Синтаксис

Object.groupBy(items, callbackFn)
  • items: массив элементов, которые вы хотите сгруппировать. Каждый элемент в массиве может быть объектом, примитивным значением или любым другим типом данных.
  • callbackFn: функция обратного вызова, которая используется для определения ключа группировки для каждого элемента. Функция обратного вызова принимает каждый элемент из массива в качестве входных данных и возвращает ключ группировки для этого элемента. Ключом группировки может быть любое значение, например строка, число или даже объект.

Пример

В приведенном выше примере группировки фруктов мы можем выполнить ту же операцию, используя Object.groupBy().

const fruitsByCalories = Object.groupBy(fruits, (fruit) => fruit.calories);
console.log(fruitsByCalories);

Однако важно отметить, что возвращаемое значение будет объектом с нулевым прототипом. Это означает, что объект не наследует никаких свойств из Object.prototype. Это также предотвращает множество угроз безопасности, что означает, что злоумышленник не сможет испортить прототип объекта.

Выход:

Map.groupBy()

Map.groupBy по существу идентичен Object.groupBy, за исключением того, что он возвращает карту. Это означает, что вы можете использовать все стандартные функции карты. Это также означает, что вы можете вернуть любой тип значения из функции обратного вызова.

Синтаксис

Map.groupBy(items, callbackFn)
  • items: массив элементов, которые вы хотите сгруппировать. Каждый элемент в массиве может быть объектом, примитивным значением или любым другим типом данных.
  • callbackFn: функция обратного вызова, которая используется для определения ключа группировки для каждого элемента. Функция обратного вызова принимает каждый элемент из массива в качестве входных данных и возвращает ключ группировки для этого элемента. Ключом группировки может быть любое значение, например строка, число или даже объект.

Пример

В приведенном ниже примере мы группируем фрукты по свойству countsWith. Обратите внимание, что объекты должны иметь одинаковую идентификацию, чтобы извлекать элементы с этой карты.

const intake = { name: "Vegetable", calories: 100, countsWith: null };
const food = { name: "Apple", calories: 30, countsWith: intake };
 
const fruits = [
  intake,
  food,
  { name: "Banana", calories: 28 },
  { name: "Avocado", calories: 28 },
];
 
const fruitsByFood = Map.groupBy(fruits, (fruit) => fruit.countsWith);
console.log(fruitsByFood.get(intake));
console.log(fruitsByFood.get({ name: "Vegetable", calories: 100, countsWith: null }));

Выход:

Мы должны использовать ту же ссылку на объект, которая использовалась в качестве ключа при заполнении карты. Поскольку метод get карты проверяет строгое равенство при сравнении ключей, передача разных ссылок на объект с одинаковыми свойствами не будет соответствовать ссылке, хранящейся на карте, что приведет к неопределенному (undefined) значению.

Совместимость браузера

Два подхода groupBy являются частью предложения TC39, которое сейчас находится на третьей стадии. Это указывает на то, что у него есть большая вероятность стать стандартом, и в результате появляются реализации.

В Chrome 117 только что добавлена поддержка этих двух подходов, и Firefox 119 последовал этому примеру. Safari ранее реализовывал подобные методы под разными названиями, я уверен, что они скоро их изменят. Эти методы находятся в Chrome, что предполагает, что они были реализованы в V8 и будут доступны в Node при следующем обновлении V8.

Заключение

Внедрение функций JavaScript groupBy для объектов и карт упрощает задачи по группировке массивов. Эти методы проще и элегантнее старых способов, позволяя разработчикам быстро группировать элементы по заданным критериям. Разработчики могут использовать Object.groupBy и Map.groupBy для создания более четкого кода и повышения безопасности, что делает их важными инструментами для манипулирования данными в JavaScript.

Источник:

#JavaScript #NodeJS
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу