2
\$\begingroup\$

I have three arrays in which first index is same, so I want to merge all three array into one array based on first index element

Input:

[[1, 'A'], [2, 'B'], [3, 'C']];
[[1, 'D'], [2, 'E'], [3, 'F']];
[[1, 'G'], [2, 'H'], [3, 'I']];

Expected output

[ 
  [ 1, 'A', 'D', 'G' ], 
  [ 2, 'B', 'E', 'H' ], 
  [ 3, 'C', 'F', 'I' ] 
]

My code:

function mergeArrays(arrays) {
  const mergedMap = new Map();

  for (const array of arrays) {
    for (const item of array) {
      const key = item[0];
      if (!mergedMap.has(key)) {
        mergedMap.set(key, [key]);
      }
      mergedMap.get(key).push(...item.slice(1));
    }
  }

  const mergedArray = Array.from(mergedMap.values());

  return mergedArray;
}

const array1 = [[1, 'A'], [2, 'B'], [3, 'C']];
const array2 = [[1, 'D'], [2, 'E'], [3, 'F']];
const array3 = [[1, 'G'], [2, 'H'], [3, 'I']];

const mergedResult = mergeArrays([array1, array2, array3]);
console.log(mergedResult);

Would you please suggest any better solution?

Please note: for the simplicity I have make first index as number but in my case it is a Date object.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

shape

Expected output

[ 
  [ 1, 'A', 'D', 'G' ], 
  [ 2, 'B', 'E', 'H' ], 
  [ 3, 'C', 'F', 'I' ] 
]

I find it slightly surprising that we want lists of [key, val1, val2...] rather than an object that maps from key to list of values. But ok, that's what you want, I won't criticize it.

I will say that, as long as we're returning an array, we might want it to be a sorted array. That makes it easier to write solid unit tests, and makes it easier to diff the output when code or data changes.


JSDoc

You offered some very helpful English prose as review context.

Now write some brief documentation comments so that context won't be lost to future maintainers.


unit tests

Adding an automated test suite to this submission wouldn't hurt.

The console.log( ... ) is a good first step. But it requires a human to eyeball the result and assess its correctness. OTOH automated tests "know the answer" so they can display Red / Green bars.


unpack

      const key = item[0];
      ... .push(...item.slice(1));

The {0, 1} subscripts aren't exactly bad but they're unnecessary.

Unpacking with a destructuring assignment would be more convenient:

      const [key, val] = item;
      ... .push(val);

Notice that this is less powerful than the OP code, and that's a Good Thing. The .slice() is very flexible, very forgiving, accommodating zero, two, or more values. If a buggy input data source or a buggy caller winds up changing from 2-tuples to something unexpected, I want to know about it, I want a fatal error to blow up unit tests and any other caller.


LGTM, ship it!

\$\endgroup\$
1
\$\begingroup\$

Would you please suggest any better solution?

Maybe different than better possible implementation is using array's reduce method twice, once for the array of arrays and once for each of the contained array...

function merge(arrays) {

    var reducer = (accumulator, element, index) => {
       accumulator[index] = accumulator[index].concat(element.slice(1));
       return accumulator;
    };
    
    var reducers = (accumulator, element, index) => {
       if ( index == 0 ) return accumulator;
       element.reduce(reducer, accumulator);
       return accumulator;
    };

    var reducee = arrays || [[]];
    return reducee.reduce(reducers, reducee[0]);
}

var array1 = [[1, 'A'], [2, 'B'], [3, 'C']];
var array2 = [[1, 'D'], [2, 'E'], [3, 'F']];
var array3 = [[1, 'G'], [2, 'H'], [3, 'I']];
var array4 = [[1, 'J'], [2, 'K'], [3, 'L']];
var array5 = [[1, 'M'], [2, 'N'], [3, 'O']];
var array6 = [[1, 'P'], [2, 'Q'], [3, 'R']];
var array7 = [[1, 'S'], [2, 'T'], [3, 'U']];
var array8 = [[1, 'V'], [2, 'W'], [3, 'X']];
var array9 = [[1, 'Y'], [2, 'Z']];


var merged = merge([ array1, array2, array3
                   , array4, array5, array6
                   , array7, array8, array9 ]);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.