Home > Software design >  Modify and Combine Array of Objects by ID
Modify and Combine Array of Objects by ID

Time:04-27

I have the following array of objects:

[
    {
        "id": 1,
        "price": 22,
        "from": "00:00:00",
        "to": "02:00:00"
    },
    {
        "id": 1,
        "price": 23,
        "from": "02:00:00",
        "to": "04:00:00"
    },
    {
        "id": 2,
        "price": 10,
        "from": "04:00:00",
        "to": "1.00:00:00"
    }
]

I need to restructure it, so it combines the objects by ID, and creates a new nested array of objects:

[
    {
        "id": 1,
        "prices": [
            {
                "price": 22,
                "from": "00:00:00",
                "to": "02:00:00"
            },
            {
                "price": 23,
                "from": "02:00:00",
                "to": "04:00:00"
            },
        ]
    }
    {
        "id": 2,
        "prices": [
            {
                "price": 10,
                "from": "04:00:00",
                "to": "1.00:00:00"
            }
        ]
    }
]

Is there a simple way to do this? I'm getting lost in split, forEach and maps. Thanks.

CodePudding user response:

One way is to use a Map to collect the prices per id. First associate an empty prices list for each id, then iterate the data to populate those arrays, and finally extract the Map values to get the result:

const data = [{"id": 1,"price": 22,"from": "00:00:00","to": "02:00:00"},{"id": 1,"price": 23,"from": "02:00:00","to": "04:00:00"},{"id": 2,"price": 10,"from": "04:00:00","to": "1.00:00:00"}];

const map = new Map(data.map(({id}) => [id, { id, prices: [] }]));
for (const {id, ...rest} of data) map.get(id).prices.push(rest);
const result = [...map.values()];

console.log(result);

CodePudding user response:

Yes, there is an easy way using reduce().

const input = [
  {
    id: 1,
    price: 22,
    from: "00:00:00",
    to: "02:00:00",
  },
  {
    id: 1,
    price: 23,
    from: "02:00:00",
    to: "04:00:00",
  },
  {
    id: 2,
    price: 10,
    from: "04:00:00",
    to: "1.00:00:00",
  },
];

const output = input.reduce((nested, cur) => {
  const objWithoutId = (({id, ...o}) => o)(cur);
  if (!nested[cur.id]) {
    nested[cur.id] = {
      id: cur.id,
      prices: [objWithoutId]
    };
  }
  else nested[cur.id].prices.push(objWithoutId);
  return nested;
}, {});

console.log(Object.values(output));

CodePudding user response:

You can use the Array.reduce method with Array.findIndex to convert your data.

const data = [{
    "id": 1,
    "price": 22,
    "from": "00:00:00",
    "to": "02:00:00"
  },
  {
    "id": 1,
    "price": 23,
    "from": "02:00:00",
    "to": "04:00:00"
  },
  {
    "id": 2,
    "price": 10,
    "from": "04:00:00",
    "to": "1.00:00:00"
  }
];

const transformedData = data.reduce((acc, item) => {
  const priceData = {
    price: item.price,
    to: item.to,
    from: item.from,
  };

  const index = acc.findIndex(({
    id
  }) => id === item.id);
  if (index === -1) {
    return [
      ...acc,
      {
        id: item.id,
        prices: [
          priceData
        ]
      },
    ];
  } else {
    acc[index].prices.push(priceData);
    return acc;
  }
}, []);

console.log(transformedData);

CodePudding user response:

const items = [
    {
        "id": 1,
        "price": 22,
        "from": "00:00:00",
        "to": "02:00:00"
    },
    {
        "id": 1,
        "price": 23,
        "from": "02:00:00",
        "to": "04:00:00"
    },
    {
        "id": 2,
        "price": 10,
        "from": "04:00:00",
        "to": "1.00:00:00"
    }
]

const result = items
.map(i => i.id)
.filter((item, pos, self) => self.indexOf(item) == pos)
.map( i => ({
  id : i, 
  prices : items
            .filter(item => item.id === i)
            .map(({ price, from, to}) => ({price, from , to}) )
    }) )
console.log(result)

  • Related