Как создать уникальный массив объекта из ответа API в JavaScript?

#javascript

#javascript

Вопрос:

У меня ниже ответа API необходимо создать уникальный массив объекта на основе идентификатора.

 const response = [{id: "ABC", value: 120, day: "MON"},{id: "ABC", value: 120, day: "TUE"},{id: "ABC", value: 120, day: "WED"},{id: "ABC", value: 120, day: "THU"},{id: "ABC", value: 120, day: "FRI"},
{id: "XYZ", value: 120, day: "TUE"},{id: "XYZ", value: 140, day: "WED"},{id: "XYZ", value: 160, day: "FRI"},{id: "SUV", value: 120, day: "MON"},{id: "SUV", value: 140, day: "TUE"}];
  

Я хочу уникальный массив объекта, как показано ниже

 obj = [{ItemID: "ABC", MON: 120, TUE: 120, WED: 120, THU: 120, FRI: 120 }, {ItemID: "XYZ", TUE: 120, WED: 140, FRI: 160 }, {ItemID: "SUV", MON: 120, TUE: 140} ];
  

Я попробовал следующий метод

 let obj = {ItemID: ""};
let arr = [];
response.forEach(el => {
let day = el.day;
  obj.ItemID = el.id;
  obj[day] = el.value
}
)

arr.push(obj);

console.log(arr)
  

Используя приведенный выше код, я всегда получаю ниже массива объекта. Я не могу добавить другой объект, когда идентификатор не соответствует

 obj = [{ItemID: "ABC", MON: 120, TUE: 120, WED: 120, THU: 120, FRI: 120 }]
  

Ответ №1:

Вы можете использовать Array.reduce наряду с Object.values .

 const response = [{id: "ABC", value: 120, day: "MON"},{id: "ABC", value: 120, day: "TUE"},{id: "ABC", value: 120, day: "WED"},{id: "ABC", value: 120, day: "THU"},{id: "ABC", value: 120, day: "FRI"},
{id: "XYZ", value: 120, day: "TUE"},{id: "XYZ", value: 140, day: "WED"},{id: "XYZ", value: 160, day: "FRI"},{id: "SUV", value: 120, day: "MON"},{id: "SUV", value: 140, day: "TUE"}];

const formatResponse = (data) => {
  const finalRes = data.reduce((res, {id, value, day}) => {
      res[id] = {
        ItemID: id,
        ...res[id],
        [day]: value
      }   
    return res;
  },{});

  return Object.values(finalRes)
}

console.log(formatResponse(response))  
 .as-console-wrapper {
  max-height: 100% !important;
}  

Использование Array.forEach также может быть достигнуто, но затем reduce становится более информативным, когда мы смотрим на метод, что мы выполняем какую-то обработку и накапливаем предоставленные данные на основе идентификатора.

 const response = [{id: "ABC", value: 120, day: "MON"},{id: "ABC", value: 120, day: "TUE"},{id: "ABC", value: 120, day: "WED"},{id: "ABC", value: 120, day: "THU"},{id: "ABC", value: 120, day: "FRI"},
{id: "XYZ", value: 120, day: "TUE"},{id: "XYZ", value: 140, day: "WED"},{id: "XYZ", value: 160, day: "FRI"},{id: "SUV", value: 120, day: "MON"},{id: "SUV", value: 140, day: "TUE"}];

const processResponse = (data) => {
  const finalRes = {};
  data.forEach(({id, value, day}) => {
    finalRes[id] = {
      ItemID: id,
      ...finalRes[id],
      [day]: value
    }
  });

  return Object.values(finalRes)
}

console.log(processResponse(response));  
 .as-console-wrapper {
  max-height: 100% !important;
}  

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

1. Спасибо, что поделились каждым способом. Это решает мою единственную проблему. Мне нужно отформатировать день, прежде чем переходить к использованию moment, чего не происходит из-за метода reduce. Но это работа с forEach

Ответ №2:

Вы можете использовать Array.prototype.reduce для накопления объектов в массиве и Array.prototype.find для поиска существующего объекта с определенным ItemID в массиве.

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

 const response = [{id: "ABC", value: 120, day: "MON"},{id: "ABC", value: 120, day: "TUE"},{id: "ABC", value: 120, day: "WED"},{id: "ABC", value: 120, day: "THU"},{id: "ABC", value: 120, day: "FRI"},
{id: "XYZ", value: 120, day: "TUE"},{id: "XYZ", value: 140, day: "WED"},{id: "XYZ", value: 160, day: "FRI"},{id: "SUV", value: 120, day: "MON"},{id: "SUV", value: 140, day: "TUE"}];

const processObject = (res) => {
  return res.reduce((acc, o) => {
    let day = acc.find(d => d.ItemID === o.id);
    if (day) {
      day[o.day] = o.value;
    } else {
      acc.push({
        ItemID: o.id,
        [o.day]: o.value
      });
    }
    return acc;
  }, [])
}
console.log(processObject(response));  

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

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

1. Можем ли мы достичь только через forEach?