Greg
Greg

Reputation: 2690

Cartesian product of 2 arrays

I have 2 arrays that I want a Cartesian product of. As an example:

Customer Array:

[10,A]
[11,B]

Debtor Array:

[88,W]
[99,X]

I want to produce a new customerDebtor array with:

[10,A,88,W]
[10,A,99,X]
[11,B,88,W]
[11,B,99,X]

I am attempting it with this code:

for (var i = 0; i < customerArray.length; i++) {
    for (var l = 0; l < debtorArray.length; l++) {
        $.each(customerArray[i], function (ndx, val) {
            //???? push values into customerDebtorMatrix array
        });
    }
}

Upvotes: 7

Views: 6655

Answers (4)

rsp
rsp

Reputation: 111316

2017 version

Using you data:

// Customer Array:
let c = [[10, 'A'], [11, 'B']];
// Debtor Array:
let d = [[88, 'W'], [99, 'X']];

all you need is one line:

let r = [].concat(...c.map(c => (d.map(d => c.concat(d)))));

or this for compatibility with older browsers that don't support the spread syntax:

let r = [].concat.apply([], c.map(c => (d.map(d => c.concat(d)))));

You can see that console.log(r); prints:

[ [ 10, 'A', 88, 'W' ],
  [ 10, 'A', 99, 'X' ],
  [ 11, 'B', 88, 'W' ],
  [ 11, 'B', 99, 'X' ] ]

which is exactly what you wanted.

No loops, no pushes to arrays, no jQuery, just a few simple function calls.

For more than two arrays, see this answer:

Upvotes: 1

user6026368
user6026368

Reputation: 31

concatMap works well here:

(function() {
    'use strict';

    // cartProd :: [a] -> [b] -> [[a, b]]
    function cartProd(xs, ys) {
        return [].concat.apply([], xs.map(function (x) {
            return [].concat.apply([], ys.map(function (y) {
                return [[x, y]];
            }));
        }));
    }

    return cartProd(["alpha", "beta", "gamma"], [1, 2, 3]);

})(); 

Returning:

[["alpha", 1], ["alpha", 2], ["alpha", 3], ["beta", 1], ["beta", 2], ["beta", 3], ["gamma", 1], ["gamma", 2], ["gamma", 3]]

Upvotes: 3

Nikos M.
Nikos M.

Reputation: 8325

Actually this would be the Kronecker (or Tensor) Product

Javascript code for the kronecker product of 2 arrays

function kronecker_product(a, b) 
{
    var i, j, k, al = a.length, bl = b.length, abl = al*bl, ab = new Array(abl);
    i = 0; j = 0;
    for (k=0; k<abl; k++)
    {
        if ( j>=bl) {j=0; i++;}
        ab[k] = [].concat(a[i],b[j]);
        j++;
    }
    return ab;
}

For disambiguation let me give the code for the cartesian product as well:

function cartesian_product(a, b) 
{
    var al = a.length, bl = b.length;
    return [a.concat(bl>al ? new Array(bl-al) : []), b.concat(al>bl ? new Array(al-bl) : [])];
}

The main difference is the number of components (length) of the final result, in kronecker the length should be the product of the lengths while in cartesian it should be the sum.

Example Kronecker

var a = ["a","b"], b = ["c","d"];
console.log(kronecker_product(a,b));

Output

[["a", "c"], ["a", "d"], ["b", "c"], ["b", "d"]]

Example Cartesian

var a = ["a","b"], b = ["c","d"];
console.log(cartesian_product(a,b));

Output

 [["a", "b"], ["c", "d"]]

Upvotes: 0

SheetJS
SheetJS

Reputation: 22905

You don't need jquery for this:

var customerArray = [[10,'A'],[11,'B']];
var debtorArray = [[88,'W'],[99,'X']];

var customerDebtorMatrix = [];
for (var i = 0; i < customerArray.length; i++) {
    for (var l = 0; l < debtorArray.length; l++) {
        customerDebtorMatrix.push(customerArray[i].concat(debtorArray[l]));
    }
}

customerDebtorMatrix will be

[ [ 10, 'A', 88, 'W' ],
  [ 10, 'A', 99, 'X' ],
  [ 11, 'B', 88, 'W' ],
  [ 11, 'B', 99, 'X' ] ]

Upvotes: 3

Related Questions