1

I have a part numbers array, ['PCI-33', 'GG-34', 'GG-32']

and I have an array of zones, ['UK', 'US', 'CA', 'MX'] etc.

I'm trying to combine both of these arrays so I can get something like this:

['PCI-33-UK', 'GG-34-UK', 'GG-32-UK', 'PCI-33-US', 'GG-34-US', ..., 'GG-32-MX']

What is an efficient way to do that?

user1354934
  • 8,139
  • 15
  • 50
  • 80
  • What have you tried so far if anything? Can you show your attempt please, this will give others something to work with and enable us to explain why your attempt isn't working also possible offer a fix on your attempt or a better method to get the outcome you expect. – NewToJS Jul 20 '17 at 21:19

4 Answers4

7

Use 2 nesting Array#map to create combine the two array, and apply Array#concat to flatten the results:

var strs1 = ['PCI-33', 'GG-34', 'GG-32'];
var strs2 = ['UK', 'US', 'CA', 'MX'];

var result = [].concat.apply([], strs1.map(function(str1) {
  return strs2.map(function(str2) {
    return str1 + '-' + str2;
  });
}));

console.log(result);

And the ES6 version that uses Array#concat with the spread syntax to flatten the sub arrays, and a template literal to create the strings.

var strs1 = ['PCI-33', 'GG-34', 'GG-32'];
var strs2 = ['UK', 'US', 'CA', 'MX'];

var result = [].concat(...strs1.map((str1) => strs2.map((str2) => `${str1}-${str2}`)));

console.log(result);
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
  • Very nice and clean. +1 – NewToJS Jul 20 '17 at 21:22
  • Can you explain why this might be better than a double for loop to construct the desired result array? This solution requires concatenation on top of the double "for loop" which almost seems unnecessary as nice as it may seem. – richardhsu Jul 20 '17 at 21:30
  • @richardhsu I see no such statement of this method being better. I understand your point but your question appears like **Ori** has suggested this is a better method over another method. – NewToJS Jul 20 '17 at 21:35
  • 2
    The main difference is Functional programming vs. imperative programming mostly. In terms of readability I find it easier to work with, but other people might disagree. Performance wise, using 2 for loops should be faster when dealing with large array, and I've UVed @PeterOlson answer as because it something that always worked :) – Ori Drori Jul 20 '17 at 21:36
  • And you should also check @James ES-1999 code that does it in a single loop :) – Ori Drori Jul 20 '17 at 21:39
  • 1
    @NewToJS Sorry, I didn't mean to imply such but cannot edit my comment now. I was merely curious of the difference and was wondering if this "might" be consider better and if so why and how. Ori, thanks for explanation. I've learned with more imperative paradigms so double for loop came more naturally so was just curious. – richardhsu Jul 20 '17 at 21:43
  • 2
    @richardhsu It's okay, I could totally understand your question but just wanted to point out how it appeared to others or at least me. I like seeing different methods as people learn from them and find benefits of them in different ways depending on their expectation/result :) – NewToJS Jul 20 '17 at 21:45
  • 1
    @NewToJS I agree, it's good to see the differences. I don't code in Javascript normally so I'm generally curious when I see other implementations and I think my biggest thing is always understanding when it may be preferred over other solutions since that helps put some context around code. Also helps me get better at coding too :) – richardhsu Jul 20 '17 at 21:51
4

Cartesian product is the mathematical term for this type of combination.

If you're not comfortable with using the "fancier" array methods, a simple way to do this is to use a nested for loop:

var parts = ['PCI-33', 'GG-34', 'GG-32'],
    zones = ['UK', 'US', 'CA', 'MX'];

var combined = [];
for(var i = 0; i < parts.length; i++) {
    for(var j = 0; j < zones.length; j++) {
        combined.push(parts[i] + "-" + zones[j]);
    }
}

Then combined will contain

["PCI-33-UK", "PCI-33-US", "PCI-33-CA", "PCI-33-MX", "GG-34-UK", "GG-34-US", "GG-34-CA", "GG-34-MX", "GG-32-UK", "GG-32-US", "GG-32-CA", "GG-32-MX"]
Peter Olson
  • 139,199
  • 49
  • 202
  • 242
3

ES-1999 code with 1 loop:

var codes = ['PCI-33', 'GG-34', 'GG-32'];
var zones = ['UK', 'US', 'CA', 'MX'];
var arr = [];

var cl = codes.length;

for (var i=0; i < cl * zones.length; i++) {
  arr.push(codes[i % cl] + "-" + zones[Math.floor(i / cl)]);
}

console.log(arr);
James
  • 20,957
  • 5
  • 26
  • 41
0

You may also do as follows;

function combine(a,[b,...bs]){
  return [a + "-" + b].concat(bs.length ? combine(a,bs) : []);
}

var arr = ['PCI-33', 'GG-34', 'GG-32'],
    brr = ['UK', 'US', 'CA', 'MX'],
    res = function runner([a,...as],bs){
            return combine(a,bs).concat(as.length ? runner(as,bs) : []);
          }(arr,brr); // Recursive IIFE here

console.log(res);
Redu
  • 25,060
  • 6
  • 56
  • 76