Home > Software engineering >  Array of objects - how to group items by property and squash data from each of grouped items into 1
Array of objects - how to group items by property and squash data from each of grouped items into 1

Time:01-31

I am trying to perfom operation on array that is described in topic. What i've done already - group by common property map data of each item to desired format. It was achieved by using reduce map function inside it. Now i need final part that is going to squash each of grouped items properties into 1. My goal is to make it work properly, ideally by extending restructuring function.

Array to restructure

const arrToRestructure = [
{
    x: "test-x1",
    y: "test-y1",
    data: [
        {id: 1, label: "label-y1-1"},
        {id: 2, label: "label-y1-2"}
    ]
},
{
    x: "test-x2",
    y: "test-y1",
    data: [
        {id: 1, label: "label-y1-3"},
        {id: 2, label: "label-y1-4"}
    ]
},
{
    x: "test-x2",
    y: "test-y2",
    data: [
        {id: 1, label: "label-y2-1"},
        {id: 2, label: "label-y2-2"}
    ]
},
]

restructuring function

const restructureArr = () => {
    const restructuredArr = arrToRestructure.reduce(
        (prevVal, nextVal) => ({
        ...prevVal,
        [nextVal["y"]]: [
            ...(prevVal[nextVal["y"]] || []),
            nextVal.data.map((nextVal) => nextVal.label),
        ]})
        ,[]);

    return restructuredArr;
}

current output

{
    "test-y1": [
        [
            "label-y1-1",
            "label-y1-2"
        ],
        [
            "label-y1-3",
            "label-y1-4"
        ]
    ],
    "test-y2": [
        [
            "label-y2-1",
            "label-y2-2"
        ]
    ]
}

desired output

{
    "test-y1": [
        "label-y1-1",
        "label-y1-2",
        "label-y1-3",
        "label-y1-4",
    ],
    "test-y2": [
        "label-y2-1",
        "label-y2-2"
    ]
}

CodePudding user response:

Simply spread the Array#map result each time:

const restructureArr = () => {
  const restructuredArr = arrToRestructure.reduce((prevVal, nextVal) => ({
    ...prevVal,
    [nextVal["y"]]: [
      ...(prevVal[nextVal["y"]] || []),
      ...nextVal.data.map((nextVal) => nextVal.label), // fix
    ]
  }) , []);
  return restructuredArr;
}

Some enhancements:

const restructureArr = (arrToRestructure = []) => 
  arrToRestructure.reduce((acc, { y, data = [] }) => ({
    ...acc,
    [y]: [
      ...(acc[y] || []),
      ...data.map(({ label }) => label),
    ]
  }), []);

const arrToRestructure = [
  { x: "test-x1", y: "test-y1", data: [ {id: 1, label: "label-y1-1"}, {id: 2, label: "label-y1-2"} ] },
  { x: "test-x2", y: "test-y1", data: [ {id: 1, label: "label-y1-3"}, {id: 2, label: "label-y1-4"} ] },
  { x: "test-x2", y: "test-y2", data: [ {id: 1, label: "label-y2-1"}, {id: 2, label: "label-y2-2"} ] }
];
console.log(restructureArr(arrToRestructure));

CodePudding user response:

You can group based on y value using array#reduce. Push all the label for same y value using array#forEach.

const arrToRestructure = [ { x: "test-x1", y: "test-y1", data: [ {id: 1, label: "label-y1-1"}, {id: 2, label: "label-y1-2"} ] }, { x: "test-x2", y: "test-y1", data: [ {id: 1, label: "label-y1-3"}, {id: 2, label: "label-y1-4"} ] }, { x: "test-x2", y: "test-y2", data: [ {id: 1, label: "label-y2-1"}, {id: 2, label: "label-y2-2"} ] }, ],
      result = arrToRestructure.reduce((r, {y, data}) => {
        r[y] ??= [];
        data.forEach(({label}) => r[y].push(label));
        return r;
      },{});
console.log(result);

CodePudding user response:

Another solution would be using Object.entries and .flat().

const obj = { "test-y1": [ [ "label-y1-1", "label-y1-2" ], [ "label-y1-3", "label-y1-4" ] ], "test-y2": [ [ "label-y2-1", "label-y2-2" ] ] }

const e = Object.entries(obj).map(el => ({[el[0]]: el[1].flat()}))

let o = Object.fromEntries(e.map(x => [Object.keys(x), Object.values(x)[0]]))

console.log(o);

  •  Tags:  
  • Related