HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

Pairwise combinations of an array in Javascript

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arraypairwisejavascriptcombinations

Problem

I wrote a Javascript function that seems to successfully generate the unique pairwise combinations of a list:

function pairwise(list) {
  var pairs = [];
  list
    .slice(0, list.length - 1)
    .forEach(function (first, n) {
      var tail = list.slice(n + 1, list.length);
      tail.forEach(function (item) {
        pairs.push([first, item])
      });
    })
  return pairs;
}

pairwise('abcd'.split(''))
// [["a","b"],["a","c"],["a","d"],["b","c"],["b","d"],["c","d"]]


I checked it by using the combinatorics formula:

$$
combinations = \frac{n(n-1)}{2}
$$

var alpha = [ "a", "b", "c", "d", "e", "f", "h", "i", "j" ];

for(var n=1;n<7;n++){ 
  console.log(
    n,                                 // number of items
    pairwise(alpha.slice(0,n)).length, // how many pairs from function?
    n*(n-1)/2                          // double check with formula above
  ); 
} 

// 1 0 0
// 2 1 1
// 3 3 3
// 4 6 6
// 5 10 10
// 6 15 15


Which looks right: there are 6 ways to chose pairs from 4 items, and so on.

It works, but I find it hard to read, and I'm not sure how to make it more readable. I'd welcome suggestions.

Solution

Pairing combinations like this is a very common thing to do in any language. There's a very 'idiomatic' way to do this type of operation:

for (int i = 0; i < length; i++) {
    for (int j = i + 1; j < length; j++) {
        // do something with pair (i,j)
    }
}


You will see, and recognize this pattern anywhere.

Because that pattern is so recognizable, I prefer seeing it rather than the slicing and dicing your code does.

Additionally, since the formula for the number of iterations is so readily available, it makes sense to pre-size the output array you use. Pre-sizing the output array will make a significant performance difference.

Further, even though the 'classic' for loop is used here, the performance will be fine. Other systems requiring slices or maps of list subsets will require additional work which, despite being 'idiomatic', will not necessarily be faster:



function pairwise(list) {

var pairs = new Array((list.length * (list.length - 1)) / 2),
pos = 0;

for (var i = 0; i
`

Code Snippets

for (int i = 0; i < length; i++) {
    for (int j = i + 1; j < length; j++) {
        // do something with pair (i,j)
    }
}

Context

StackExchange Code Review Q#75658, answer score: 16

Revisions (0)

No revisions yet.