Реструктурировать массив объектов на более глубокий уровень

#javascript #algorithm #data-structures

#javascript #алгоритм #структуры данных

Вопрос:

Я пытаюсь создать таблицу, используя базовый HTML (JSX). Каждая строка должна иметь уникальную дату, за которой следует количество яблок, клубники, бананов и апельсинов, проданных в этот конкретный день.

Данные, которые я получаю от моего API, затрудняют создание таблицы, поэтому мне нужно ее реструктурировать.

 const data = [
  {
    id: 1,
    date_sold: "2020-11-14",
    fruit: "Apples",
    amount: 9,
  },
  {
    id: 2,
    date_sold: "2020-11-14",
    fruit: "Strawberries",
    amount: 2,
  },
  {
    id: 3,
    date_sold: "2020-11-13",
    fruit: "Apples",
    amount: 1,
  },
  {
    id: 4,
    date_sold: "2020-11-13",
    fruit: "Oranges",
    amount: 4,
  },
  {
    id: 5,
    date_sold: "2020-11-13",
    fruit: "Bananas",
    amount: 2,
  },
  {
    id: 6,
    date_sold: "2020-11-13",
    fruit: "Strawberries",
    amount: 3,
  },
  {
    id: 7,
    date_sold: "2020-11-12",
    fruit: "Apples",
    amount: 2,
  },
  {
    id: 8,
    date_sold: "2020-11-12",
    fruit: "Bananas",
    amount: 5,
  },
  {
    id: 9,
    date_sold: "2020-11-12",
    fruit: "Strawberries",
    amount: 2,
  },
  {
    id: 10,
    date_sold: "2020-11-11",
    fruit: "Apples",
    amount: 8,
  },
  {
    id: 11,
    date_sold: "2020-11-11",
    fruit: "Oranges",
    amount: 3,
  },
];
  

Чтобы это выглядело так:

 const newData = {
  "2020-11-14": { Bananas: 0, Apples: 9, Strawberries: 2, Oranges: 0 },
  "2020-11-13": { Bananas: 2, Apples: 1, Strawberries: 3, Oranges: 4 },
  "2020-11-12": { Bananas: 5, Apples: 2, Strawberries: 2, Oranges: 0 },
  "2020-11-11": { Bananas: 0, Apples: 8, Strawberries: 0, Oranges: 3 },
};
  

Ответ №1:

Это можно сделать с помощью Array.prototype.reduce .

 const data = [
  {
    id: 1,
    date_sold: "2020-11-14",
    fruit: "Apples",
    amount: 9,
  },
  {
    id: 2,
    date_sold: "2020-11-14",
    fruit: "Strawberries",
    amount: 2,
  },
  {
    id: 3,
    date_sold: "2020-11-13",
    fruit: "Apples",
    amount: 1,
  },
  {
    id: 4,
    date_sold: "2020-11-13",
    fruit: "Oranges",
    amount: 4,
  },
  {
    id: 5,
    date_sold: "2020-11-13",
    fruit: "Bananas",
    amount: 2,
  },
  {
    id: 6,
    date_sold: "2020-11-13",
    fruit: "Strawberries",
    amount: 3,
  },
  {
    id: 7,
    date_sold: "2020-11-12",
    fruit: "Apples",
    amount: 2,
  },
  {
    id: 8,
    date_sold: "2020-11-12",
    fruit: "Bananas",
    amount: 5,
  },
  {
    id: 9,
    date_sold: "2020-11-12",
    fruit: "Strawberries",
    amount: 2,
  },
  {
    id: 10,
    date_sold: "2020-11-11",
    fruit: "Apples",
    amount: 8,
  },
  {
    id: 11,
    date_sold: "2020-11-11",
    fruit: "Oranges",
    amount: 3,
  },
];

const output = data.reduce((acc, cur) => {
  acc[cur.date_sold] ? acc[cur.date_sold][cur.fruit] = cur.amount : acc[cur.date_sold] = {
    [cur.fruit]: cur.amount
  };
  return acc;
}, {});
console.log(output);  

Ответ №2:

Вам нужно создавать новые данные по частям. Сначала соберите все финики и фрукты, например:

 const dates = [];
const fruits = [];

for (const item of data) {
  if (!dates.includes(data.date_sold))
    dates.push(data.date_sold);
  if (!fruits.includes(data.fruit))
    fruits.push(data.push);
}
  

Затем вы можете создать свой объект newDate, например:

 const newData = Object.fromValues(
  dates.map(function (date) {
    const fruitsCount = Object.fromValues(
      fruits.map(function (fruit) {
        return [fruit, 0];
      })
    });
    for (const item of data) {
      if (item.date === date) {
        fruitsCount[item.fruit]  = item.amout;
      }
    }
    return [data, fruitsCount];
);
  

Ответ №3:

Я думаю, что следующее решение более читабельно.

 const result = {};

data.forEach(el => {
    const keys = Object.keys(result);
    if (keys.indexOf(el.date_sold) > -1) {
        const amount = result[el.date_sold][el.fruit];
        result[el.date_sold][el.fruit] = (amount || 0)   el.amount;
    } else {
        result[el.date_sold] = {
            [el.fruit]: el.amount
        };
    }
});