25

Is there a feature in JavaScript 6 that allows to map over multiple arrays ?

Something like a zipper :

 var myFn = function (a, b) { console.log(a, b);}
  var arr1 = ['a', 'b', 'c'];
  var arr2 = [1, 2, 3];

  arr1.map(myFn, arr2); // imaginary syntax.
  // prints :
  // a 1
  // b 2
  // c 3
1

6 Answers 6

45

As the other answer points out, this is commonly known as a zip. It can be implemented as:

let zipped = arr1.map((x, i) => [x, arr2[i]]);

Or as a function, basically:

let zip = (a1, a2) => a1.map((x, i) => [x, a2[i]]); 

Which would let you do:

zip(["a","b","c"], [1,2,3]); // ["a", 1], ["b", 2], ["c", 3]
Sign up to request clarification or add additional context in comments.

Comments

10

Unfortunately, no. What you are looking for is commonly called zip or zipWith. See lodash's implementation for a reference: https://lodash.com/docs#zipWith

4 Comments

Aww. I know about lodash, but I can't use it right now. Do you have a source for that missing feature ? (Quite hard I know).
No I am not asking for code? How do you know that it is missing ? Obviously "missing features" are not represented in the ES6 standard. So do you have a reference to point that it is missing ?
Gotcha! Here's a link to the reference for Array on MDN. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… It lists all of the methods available on Array.prototype, and you will find that the functionality you are looking for is not present.
Thanks, I will accept your answer as soon as I can.
8

You could also use reduce to get the desired outcome:

var arr1 = ['a', 'b', 'c'];
var arr2 = [1, 2, 3];

arr1.reduce((acc, current, index) => {
   console.log(current, arr2[index])
   return [...acc, current, arr2[index]]
}, [])

// a 1
// b 2
// c 3
// returns ["a", 1, "b", 2, "c", 3]

2 Comments

This isn't what the user wanted, they wanted ["a", 1], ["b", 2], ["c", 3], not ["a", 1, "b", 2, "c", 3] right?
Don't do that: it creates a new array on each iteration.
1

Took reference from @Onaracs 's answer and edited it.

const arr1 = ['a', 'b', 'c']
const arr2 = [1, 2, 3]

const arr3 = arr1.reduce((acc, current, index) => {
  return [...acc, [current, arr2[index]]]
}, [])

console.log(arr3)

Comments

0

Late to the party, but here's my solution.

// Custom zip
const zip = function (N, callback) {
    if (this.length === 0 || N.length === 0 || this.length !== N.length) {
        console.error(`Arrays are of different lengths or empty.`);
        return;
    }
    for (let i = 0; i < this.length; i++) {
        callback(this[i], N[i], i, this, N);
    }
};

// Custom zipMap
const zipMap = function (N, callback) {
    if (this.length === 0 || N.length === 0 || this.length !== N.length) {
        console.error(`Arrays are of different lengths or empty.`);
        return;
    }
    const results = [];
    for (let i = 0; i < this.length; i++) {
        results.push(callback(this[i], N[i], i, this, N));
    }
    return results;
};

// Basic Usage:
const numberArr = [1,2,3];
const stringArr = ['a','b','c'];

// Add zip function to array as a property.
numberArr.zip = zip;
//or
numberArr.zipMap = zipMap;

const callback = function(itemA, itemB, index, ArrayA, ArrayB){
    console.log(itemA + itemB)
}

numberArr.zip(stringArr, callback);

// prints :
// a1
// b2
// c3

You can also add the functions to Array.prototype but I don't recommend doing so, unless it's only going to be used in your code base. This post explains why it should be avoided.

//Use with caution
Object.defineProperty(Array.prototype, 'zip', {
    value: zip
});

Object.defineProperty(Array.prototype, 'zipMap', {
    value: zipMap
});

Comments

0

To answer the original question: there’s no way to map over multiple arrays, so you have to rely on the index.

Here is a basic implementation:

function mmap(f, array1, ...rest_arrays) {
    return array1.map((value, index) => f(value, ...rest_arrays.map(x => x[index])));
}

console.log(mmap((name, age) => `${name}: ${age}`,
                 ['Alice', 'Bob'],
                 [32, 21]));
// => ["Alice: 32", "Bob: 21"]

I’m not 100% sure how to type this properly in TypeScript, but if all arrays have the same type that’s easier:

// T1: type of the elements of the arrays
// T2: type of the return value of the function
function mmap<T1, T2>(f: (x: T1, ...rest: T1[]) => T2, array1: T1[], ...rest_arrays: T1[][]): T2[] {
    return array1.map((value, index) => f(value, ...rest_arrays.map(x => x[index])));
}

Then you can use it to implement zip: mmap(Array, ...arrays):

const arr1 = ['a', 'b', 'c'];
const arr2 = [1, 2, 3];

console.log(mmap(Array, arr1, arr2));
// => [ [ 'a', 1 ], [ 'b', 2 ], [ 'c', 3 ] ]

// It works on any number of arrays:
console.log(mmap(Array, arr1, arr2, arr1, arr2));
// => [ [ 'a', 1, 'a', 1 ], [ 'b', 2, 'b', 2 ], [ 'c', 3, 'c', 3 ] ]

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.