-4

I have a JSONLines file containing thousands of items and I need to merge all of them but for arrays instead of merge need to concatenate them. I don't have the item schema so need to dynamically do this.

{title: 'test', data: [1]}
{title: 'test', data: [2]}
{title: 'test1', data: [3]}

and output will be something like this

{title: 'test1', data: [1,2,3]}

not sure what is the best performing way I can do.

Mini
  • 1,138
  • 9
  • 24
  • 1
    Why would 'test' and 'test1' be lumped together? Otherwise, this would be the same as [Group array items using object](https://stackoverflow.com/q/31688459/215552). If you can provide an algorithm that describes how you are grouping items together besides the obvious `element[i].title == element[i-1].title`, and you're willing to show what you've tried, and what research you've done, someone might be willing to help. As it is, it seems like you want someone to do your research and/or write the code for you... – Heretic Monkey Apr 14 '22 at 02:06
  • Thanks, dear Heretic. I will try to do my best next time – Mini Apr 14 '22 at 03:09
  • Does this answer your question? [Group array items using object](https://stackoverflow.com/questions/31688459/group-array-items-using-object) – Heretic Monkey Apr 14 '22 at 11:29

1 Answers1

-1

No so complicated You can separate the steps. Like:

const array = [
  { title: 'test', data: [1], data2: ['data1', 'data2'] },
  { title: 'test', data: [2], data2: [1, 2] },
  { title: 'test1', data: [3], data2: [1, 2, 3] },
  { title: 'test1', data2: [1, 2, 3] },
  { title: 'test1', data2: 'string' },
  { title: 'test3', data2: 69 },
];

const mergeAllKeys = (newArr, val, ix, mergeOn) => {
  return Object.keys(newArr[ix])
    .filter((k) => k !== mergeOn)
    .reduce((obj, k) => ({
      ...obj,
      [k]: [
        ...newArr[ix][k],
        ...(Array.isArray(val[k]) ? val[k] : [val[k]]),
      ].filter((v) => v),
    }), {});
};

const keysToArray = (val, mergeOn) => {
  return Object.keys(val)
    .filter((k) => k !== mergeOn)
    .reduce((o, k) => ({ ...o, [k]: Array.isArray(val[k]) ? val[k] : [val[k]] }), {});
};


function mergeBy(arr, mergeOn) {
  const memo = [];
  return arr.reduce((newArr, val) => {
    const ix = memo.findIndex((v) => v === val[mergeOn]);
    if (ix > -1) {
      newArr[ix] = {
        [mergeOn]: newArr[ix][mergeOn],
        ...mergeAllKeys(newArr, val, ix, mergeOn),
      };
      return newArr;
    }
    memo.push(val[mergeOn]);
    return [
      ...newArr,
      {
        [mergeOn]: val[mergeOn],
        ...keysToArray(val, mergeOn),
      },
    ];
  }, []);



And later put it all together:

const array = [
  { title: 'test', data: [1], data2: ['data1', 'data2'] },
  { title: 'test', data: [2], data2: [1, 2] },
  { title: 'test1', data: [3], data2: [1, 2, 3] },
  { title: 'test1', data2: [1, 2, 3] },
  { title: 'test1', data2: 'string' },
  { title: 'test3', data2: 69 },
];

function mergeBy(arr, mergeOn) {
  const memo = [];
  return arr.reduce((newArr, val) => {
    const ix = memo.findIndex((v) => v === val[mergeOn]);
    if (ix > -1) {
      newArr[ix] = {
        [mergeOn]: newArr[ix][mergeOn],
        ...Object.keys(newArr[ix])
          .filter((k) => k !== mergeOn)
          .reduce((obj, k) => ({
            ...obj,
            [k]: [
              ...newArr[ix][k],
              ...(Array.isArray(val[k]) ? val[k] : [val[k]]),
            ].filter((v) => v),
          }), {}),
      };
      return newArr;
    }
    memo.push(val[mergeOn]);
    return [
      ...newArr,
      {
        [mergeOn]: val[mergeOn],
        ...Object.keys(val)
          .filter((k) => k !== mergeOn)
          .reduce((o, k) => ({ ...o, [k]: Array.isArray(val[k]) ? val[k] : [val[k]] }), {}),
      },
    ];
  }, []);
}

const funkyMerge = mergeBy(array, 'title');
console.log('funkyMerge: ', funkyMerge);
Omar Omeiri
  • 1,506
  • 1
  • 17
  • 33