0

I have an array of objects each with a nested array and a non-unique ID. I would like to concatenate the objects subarrays where the ID's match.

With the following input:

inputArr = [
            {id: 1,
             days: ["2022-09-05", 
                    "2022-09-06", 
                   ]
             },
            {id: 2,
             days: ["2022-10-05", 
                    "2022-10-06"]
            },
            {id: 1,
             days: ["2022-09-05", 
                    "2022-09-06", 
                    "2022-09-07", 
                    "2022-09-08"]
            },
             {id: 2,
              days: ["2022-10-05", 
                    "2022-10-08"]
             },
            ] 

My desired output is as follows:

outputArr = [
            {id: 1,
             days: ["2022-09-05", 
                    "2022-09-06",
                    "2022-09-07", 
                    "2022-09-08" 
                   ]
             },
            {id: 2,
             days: ["2022-10-05", 
                    "2022-10-06",
                    "2022-10-08"]
            },
            ] 

Ideally I would like to do this without the use of for loops and instead use a map, filter, reduce strategy. I have tried a couple of variations but am having trouble with the nesting. Thanks in advance for the help! Its greatly appreciated.

Code4fun
  • 21
  • 2
  • or: [Group array items using object](https://stackoverflow.com/questions/31688459/group-array-items-using-object) – pilchard Jul 29 '22 at 21:30

2 Answers2

0

My approach using reduce

const inputArr = [
  { id: 1, days: ["2022-09-05", "2022-09-06"] },
  { id: 2, days: ["2022-10-05", "2022-10-06"] },
  { id: 1, days: ["2022-09-05", "2022-09-06", "2022-09-07", "2022-09-08"] },
  { id: 2, days: ["2022-10-05", "2022-10-08"] },
];
const outputArr = inputArr.reduce((accArr, currObj) => {
  let ind = accArr.findIndex((obj) => obj.id == currObj.id);
  if (ind < 0) {
    accArr.push({ ...currObj, days: [...new Set(currObj.days)].slice().sort() });
  } else {
    accArr[ind].days = [...new Set([...accArr[ind].days, ...currObj.days])].slice().sort();
  }
  return accArr;
}, []);
console.log(JSON.stringify(outputArr, null, 4));

Result

[
    {
        "id": 1,
        "days": [
            "2022-09-05",
            "2022-09-06",
            "2022-09-07",
            "2022-09-08"
        ]
    },
    {
        "id": 2,
        "days": [
            "2022-10-05",
            "2022-10-06",
            "2022-10-08"
        ]
    }
]

Note: [...new Set(array)] to get only unique values from that array.

XMehdi01
  • 5,538
  • 2
  • 10
  • 34
  • There's no need to parse the dates; in that format they'll sort naturally with just `.sort()`. – Heretic Monkey Jul 29 '22 at 21:25
  • Nice catch, I remove that helper function of sorting ,Plus I added method slice before sorting since slice modify the array I do `slice` to just sort copy not the original! – XMehdi01 Jul 29 '22 at 21:31
  • Within this solution is there a way to count the number of times a concatenation has happened? I.e in the output array there would be a "count" field which for this example would equal 1 for each object – Code4fun Jul 31 '22 at 20:34
  • @Code4fun First is this question answer your question? Second I don't really know what do you mean by concatenation, you could do another question and explain more about what you need and I'm or the community gonna help you! – XMehdi01 Jul 31 '22 at 20:42
0

Not an elegant solution but something like this could work:

let inputArr = [
  { id: 1, days: ["2022-09-05", "2022-09-06"] },
  { id: 2, days: ["2022-10-05", "2022-10-06"] },
  { id: 1, days: ["2022-09-05", "2022-09-06", "2022-09-07", "2022-09-08"] },
  { id: 2, days: ["2022-10-05", "2022-10-08"] },
];
let outputObj = {};
inputArr.forEach(
  (item) =>
    (outputObj[item.id] = outputObj[item.id]
      ? [...outputObj[item.id], ...item.days]
      : item.days)
);
let outputArr = Object.entries(outputObj).map((item) => ({
  id: parseInt(item[0]),
  days: Array.from(new Set(item[1])),
}));

Output:

[
  {
    id: 1,
    days: [ '2022-09-05', '2022-09-06', '2022-09-07', '2022-09-08' ]
  },
  { id: 2, days: [ '2022-10-05', '2022-10-06', '2022-10-08' ] }
]
Joacim Norbeck
  • 203
  • 1
  • 6