Lodash unzipWith: Modifying Reconstructed Groups

The _.unzipWith method in Lodash allows developers to disaggregate an array of grouped elements while simultaneously applying a custom transformation to each regrouped set. While standard unzipping simply transposes a two-dimensional array by grouping elements that share the same index, _.unzipWith introduces an iteratee function. This article explains how _.unzipWith processes grouped arrays and uses custom functions to alter, aggregate, or format data on the fly.

Understanding the Role of _.unzipWith

In data processing, arrays often arrive in grouped pairs or tuples, such as coordinates, key-value sets, or aligned column rows. Lodash provides _.unzip to reverse this structure, turning an array of rows into an array of columns.

However, _.unzip alone only reorganizes the positions of elements. To compute values or transform the data, developers traditionally had to chain _.unzip with a .map() call. The _.unzipWith method streamlines this operation into a single step by accepting an iteratee function that directly governs how each reconstructed group is produced.

How the Iteratee Modifies Reconstructed Groups

The method accepts two arguments: the array of grouped elements to process, and the iteratee callback.

_.unzipWith(array, [iteratee=_.identity])

During execution, _.unzipWith determines the new groups by index, exactly like _.unzip. Instead of immediately pushing the raw array of matched elements into the final result, it passes those elements as individual arguments into the iteratee function. The return value of the iteratee then becomes the item at that position in the final returned array.

Example: Performing Arithmetic Aggregation

Consider an array containing two sub-arrays where corresponding indices represent values that need to be summed together:

const chunkedNumbers = [
  [10, 20, 30],
  [1, 2, 3]
];

const totals = _.unzipWith(chunkedNumbers, (first, second) => first + second);

console.log(totals);
// Output: [11, 22, 33]

In this case, the first elements (10 and 1) are passed into the iteratee, producing 11. Next, 20 and 2 yield 22, followed by 30 and 3 yielding 33.

Example: Dynamic Object Construction

The iteratee is not limited to mathematical operations; it can completely reshape the data type of the reconstructed groups. For instance, separate arrays of attributes can be merged into structured objects:

const dataset = [
  ['Alice', 'Bob', 'Charlie'],
  [25, 30, 35],
  ['Engineer', 'Designer', 'Manager']
];

const profiles = _.unzipWith(dataset, (name, age, role) => ({
  name,
  age,
  role
}));

console.log(profiles);
// Output:
// [
//   { name: 'Alice', age: 25, role: 'Engineer' },
//   { name: 'Bob', age: 30, role: 'Designer' },
//   { name: 'Charlie', age: 35, role: 'Manager' }
// ]

Handling Variable-Length Groups

When unzipping collections with an arbitrary number of sub-arrays, you can use rest parameters (...values) within the iteratee. This allows the callback to accept any number of inputs per reconstructed column:

const matrix = [
  [1, 2],
  [10, 20],
  [100, 200]
];

const averages = _.unzipWith(matrix, (...values) => {
  const sum = values.reduce((acc, curr) => acc + curr, 0);
  return sum / values.length;
});

console.log(averages);
// Output: [37, 74]

Summary

By taking an iteratee as a parameter, _.unzipWith bridges transposition and transformation. It unpacks parallel arrays, feeds each corresponding set of items directly into your function as arguments, and builds a new array from the results, eliminating intermediate array allocations and keeping code concise.