Search code examples
javascriptmathunderscore.jsset-theory

Reverse of a cartesian product


Given the code below:

function cartesianProductOf() {
    return _.reduce(arguments, function(a, b) {
        return _.flatten(_.map(a, function(x) {
            return _.map(b, function(y) {
                return x.concat([y]);
            });
        }), true);
    }, [ [] ]);
};

var cp = cartesianProductOf([1, 2], [3, 4], ['a', 'b']); // [[1,3,"a"],[1,3,"b"],[1,4,"a"],[1,4,"b"],[2,3,"a"],[2,3,"b"],[2,4,"a"],[2,4,"b"]] 

I am looking for a way to reverse the process, such that

reverseCartesian(cp,[3,4]);  // [[1,'a'],[1,'b'],[2,'a'],[2,'b']] 

Solution

  • I don't think this would perform faster with real data, but you can do it like this

    function reverseCartesian(cp, arr) {
        return _.chain(cp)
            .map(_.partial(_.difference, _, arr))
            .uniq(function(currentItem) {
                return currentItem.join("|");
            })
            .value();
    }
    
    console.log(reverseCartesian(cp, [3, 4]));
    // [ [ 1, 'a' ], [ 1, 'b' ], [ 2, 'a' ], [ 2, 'b' ] ]
    

    Note: This will not work properly if the arrays have elements with | in them. Choose this character (or set of characters) carefully in such a way that they will not occur in the arrays.