0

Let's say I have two arrays:

var a = [[1, 10], [2, 10], [3, 10], [4, 10], [5, 10]];
var b = [[1, 20], [3, 20], [4, 20]];

I want to combine these two into a new array:

var c = [[1, 10, 20], [2, 10], [3, 10, 20], [4, 10, 20], [5, 10]];

What's the best way to go about doing this. I'll update my question in a second with what I've tried to do.

var c = [];
for(var i = 0; i < a.length; i++) {
  for(var j = 0; j < b.length; j++) {
    if(a[i][0] == b[j][0]) {
      // Push b value into a
      a[i][0].push(b[j][1]);
    } else {
      // Don't do anything...
    }
  }
}

c = a;  // Useless code here but just wanted to return c
return c;
sir_thursday
  • 5,270
  • 12
  • 64
  • 118
  • You could use map on the first array, loop through each of the second array, compare the first numbers and then append the first array with the numbers it doesn't already contain? – JakeSidSmith May 26 '14 at 15:38
  • 1
    don't make yourself life harder by giving your iterators arbitrary names. use ai, bi, ci instead of i,j,... to avoid confusion (I started naming them like you myself and have to now force myself to overcome this bad habit) – Winchestro May 26 '14 at 15:43

2 Answers2

2

Example

var a = [[1, 10], [2, 10], [3, 10], [4, 10], [5, 10]];
var b = [[1, 20], [3, 20], [4, 20]];
var c = [];

// Loop over a
for (var n = 0; n < a.length; n++) {
    // Create copy of a's value
    var subA = a[n].slice(0);
    // Loop over b
    for (var i = 0; i < b.length; i++) {
        var subB = b[i];
        // Check if a contains b
        if (subA.indexOf(subB[0]) === 0) {
            // Add b to new a value
            subA.push(subB[1]);
        }
    }
    // Add new value to c
    c.push(subA);
}

console.log(a)
console.log(c);

Edit 1: updated for loop

Edit 2: If first item equals first item

Edit 3: Slice a to retain original values

JakeSidSmith
  • 819
  • 6
  • 12
  • Also, [don't use `for in` loops on arrays](https://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea) – Bergi May 26 '14 at 15:53
  • That wasn't in the question when I started writing my answer. – JakeSidSmith May 26 '14 at 15:55
  • This still creates an entirely new array with the same structure, and is easier to understand. – JakeSidSmith May 26 '14 at 15:57
  • Oh, I see. Yet, it's not an entirely new array, it does modify the `subA` arrays instead of copying them. Also, OP doesn't really want `if a contains b` but rather `subA[0] == subB[0]` – Bergi May 26 '14 at 16:00
  • You have a good point about modifying "a" actually. Didn't think about that. – JakeSidSmith May 26 '14 at 16:03
  • +1, this is much more clean than the original code now - even if it's still as inefficient :-) – Bergi May 26 '14 at 16:15
  • I tried using JQuerys map and each originally, which is easier to read, but it loops through all the sub array, which is not desired. – JakeSidSmith May 26 '14 at 16:19
1

Why don't you use plain arrays? They can be sparse.

var a = [10, 10, 10, 10, 10];
var b = [20,   , 20, 20];

Now get them into one array:

var c = new Array(Math.max(a.length, b.length));
for (var i=0; i<c.length; i++)
    if (i in a && i in b)
        c[i] = [a[i], b[i]];
    else if (i in a)
        c[i] = [a[i]];
    else if (i in b)
        c[i] = [b[i]];

For the case that your objects (the items really don't have to be arrays) consist of a non-integer indexing values, you might use a simple standard merge algorithm on the two sorted lists. It will run in O(n+m), not in O(n*m) as your solution. See this answer for an example implementation and further pointers.

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    My example above is simplified from what I'm actually doing. In my case, each array is actually a 2-D array of dates and values. – sir_thursday May 26 '14 at 15:39