ES6 извлечение массива фильтрация массива объектов с массивом идентификаторов

#javascript #ecmascript-6

Вопрос:

Мне нужно извлечь из carriers кода элементы, присутствующие в active массиве:

 const carriers = [
  { id: 0, code: "gls" },
  { id: 1, code: "tnt" },
  { id: 2, code: "fedex" },
  { id: 3, code: "ups" },
  { id: 4, code: "postnl" },
];
const active = [0, 2, 3];
const active_code = [];

let result = carriers.filter((c) => active.includes(Number(c.id)));
console.log(result);

result.forEach((item) => {
  active_code.push(item.code);
});
console.log(active_code); 

Ожидаемый результат:

 ["gls", "fedex", "ups"]
 

Приведенный выше код работает, но я хотел бы узнать, есть ли лучший/более простой/элегантный способ получить тот же результат?

Спасибо

Ответ №1:

Для начала можно настроить его, сопоставив вместо создания пустого массива и нажав на него.

 carriers.filter(i=>active.includes( i.id)).map(i=>i.code)
 

Комментарии:

1. Я думаю, что это не лучшее решение, но, ИМХО, его легче всего понять тем, кто столкнется с той же проблемой с ограниченными навыками, что и я

Ответ №2:

Сопоставьте active массив .find , указав соответствующую несущую.

 const carriers = [
                  {"id":0,"code":"gls"},
                  {"id":1,"code":"tnt"},
                  {"id":2,"code":"fedex"}, 
                  {"id":3,"code":"ups"},
                  {"id":4,"code":"postnl"}
                 ];
const active = [0,2,3];

const result = active.map(id => carriers.find(c => c.id === id).code);
console.log(result); 

Для меньшей вычислительной сложности сначала превратите его carriers в структуру, индексируемую идентификатором.

 const carriers = [
                  {"id":0,"code":"gls"},
                  {"id":1,"code":"tnt"},
                  {"id":2,"code":"fedex"}, 
                  {"id":3,"code":"ups"},
                  {"id":4,"code":"postnl"}
                 ];
const active = [0,2,3];

const carriersById = Object.fromEntries(
  carriers.map(c => [c.id, c])
);
const result = active.map(id => carriersById[id].code);
console.log(result); 

Комментарии:

1. оба варианта являются идеальным решением

Ответ №3:

1) Вы можете достичь результата с помощью карты.

 const carriers = [
  { id: 0, code: "gls" },
  { id: 1, code: "tnt" },
  { id: 2, code: "fedex" },
  { id: 3, code: "ups" },
  { id: 4, code: "postnl" },
];
const active = [0, 2, 3];

const map = new Map(carriers.map(({ id, code }) => [id, code]));
const active_code = active.map((id) => map.get(id));

console.log(active_code); 

2) Вы также можете получить результат с помощью набора

 const carriers = [
  { id: 0, code: "gls" },
  { id: 1, code: "tnt" },
  { id: 2, code: "fedex" },
  { id: 3, code: "ups" },
  { id: 4, code: "postnl" },
];
const active = [0, 2, 3];

const set = new Set(active);
const active_code = carriers
  .filter((o) => set.has(o.id))
  .map(({ code }) => code);

console.log(active_code); 

Ответ №4:

Я бы сопоставил carriers данные active_code напрямую.

Вы также можете создать active_ids объект, чтобы избежать вызова includes для каждой записи.

 const carriers = [
    { "id": 0, "code": "gls" },
    { "id": 1, "code": "tnt" },
    { "id": 2, "code": "fedex" },
    { "id": 3, "code": "ups" },
    { "id": 4, "code": "postnl" }
];
const active = [0, 2, 3];

const active_ids = Object.fromEntries(active.map(i => [i, true]));

let active_code = carriers
    //.filter(c => active.includes(c.id))
    .filter(c => active_ids[c.id])         // faster if many items?
    .map(c => c.code)

console.log(active_code);

// expected ["gls", "fedex", "ups"]
console.assert(active_code[0] === "gls")
console.assert(active_code[1] === "fedex")
console.assert(active_code[2] === "ups")