1

I would like to compare 2 "multidimensional" arrays (arrays nested in arrays).

var old_dataArray=new Array(("id-2", "message", "user"), ("id-1", "message", "user"), ("id-0", "message", "user"));
var new_dataArray=new Array(("id-3", "message", "user"), ("id-2", "message", "user"), ("id-1", "message", "user"));

in this case, I would like to get the array("id-3", "message", "user") which is contained only in "old_dataArray" and not in "new_dataArray".

I've tried with the array_diff function presented here. http://phpjs.org/functions/array_diff:309 But it doesn't really work !.

Upendra Chaudhari
  • 6,473
  • 5
  • 25
  • 42
Mikou
  • 579
  • 1
  • 8
  • 17
  • 3
    You don't have nested arrays there because what you intended to be the inner arrays have parentheses instead of square brackets. Speaking of which, don't bother with the `new Array(1,2,3)` syntax, just use array literal `[1,2,3]` syntax. When you say you want to find nested arrays contained only in `old_dataArray` and not `new_dataArray` do you mean to compare each nested array by identity or by value? (I.e., compare based on whether they reference the same array object or find them if they have the some number of elements with the same values?) – nnnnnn Sep 29 '11 at 12:10
  • @nnnnnn: I guess you didn't want the upvotes from answering this in the proper place, eh? – hugomg Sep 29 '11 at 12:28
  • 1
    @missingno - Oh well, upvotes aren't everything. I didn't post an answer because (as per the second half of my comment) I felt the question was unclear about how to compare the nested arrays. I figured once this was clarified I could post an answer if nobody else had yet, but in the mean time at least I could point out about the square brackets. – nnnnnn Sep 29 '11 at 12:45

2 Answers2

3

From what I understand, you want to get all arrays in new_dataArray that are not in old_dataArray and I'm assuming that if the first element in each (the 'id-n' element) is the same, then so is the rest of the array. You can do so like this:

// create an array to store our results:
var results = new Array();

// loop through new_dataArray:
outerloop:
for (var i = 0; i < new_dataArray.length; ++i) {

    // loop through old_dataArray to compare the i'th element
    // in new_dataArray with each in old_dataArray:
    for (var j = 0; j < old_dataArray.length; ++j) {

        // check if the ids are the same
        if (new_dataArray[i][0] == old_dataArray[j][0])
            // yes it's there, so move on to the next element of new_dataArray
            continue outerloop;

    }

    // if we get here, continue outerloop; was never called so 
    // this element is not in old_dataArray
    results.push(new_dataArray[i]);

}

// now results contains all arrays that are in new_dataArray 
// but not in old_dataArray

EDIT: If, however, you want ALL the elements in each array to be equal, not just the first (id-n) element, use this:

// create an array to store our results:
var results = new Array();

// loop through new_dataArray:
outerloop:
for (var i = 0; i < new_dataArray.length; ++i) {

    // loop through old_dataArray to compare the i'th element
    // in new_dataArray with each in old_dataArray:
    innerloop:
    for (var j = 0; j < old_dataArray.length; ++j) {

        // check if the arrays are the same size:
        if (new_dataArray[i].length != old_dataArray[j].length)
            // no, so they must be different
            continue innerloop;

        // check if the arrays have the same values
        for (var k = 0; k < old_dataArray[j].length; ++k) {

            if (new_dataArray[i][k] != old_dataArray[j][k])
                // the k'th element is different
                continue innerloop;
        }

        // if we get here, then we have found a match, so move on
        continue outerloop;

    }

    // if we get here, continue outerloop; was never called so 
    // this element is not in old_dataArray
    results.push(new_dataArray[i]);

}

// now results contains all arrays that are in new_dataArray 
// but not in old_dataArray
daiscog
  • 11,441
  • 6
  • 50
  • 62
  • +1 for the `continue outerloop`. (I know some people don't like labels and continues, but then I know some people so stuffy they wouldn't even break out of a non-nested loop; I _do_ like the `continue outerloop` syntax, especially with meaningful comments like yours.) – nnnnnn Sep 29 '11 at 12:56
  • Thank you. I always try to minimise use of temporary variables and unnecessary conditional checks. Every clock-cycle counts! – daiscog Sep 29 '11 at 12:57
0
var old_dataArray = [["id-2", "message", "user"], ["id-1", "message", "user"], ["id-0", "message", "user"]];
var new_dataArray = [["id-3", "message", "user"], ["id-2", "message", "user"], ["id-1", "message", "user"]];

var result = [];

for (var i = 0; i < new_dataArray.length ; i++) {
    var isInOldArray = false;
    console.log(new_dataArray[i][0]);

    for (var j = 0; j < old_dataArray.length; j++) {
         if (old_dataArray[j][0] === new_dataArray[i][0]) {
             isInOldArray = true;
             break;
         };
    };

    if (!isInOldArray) {
        result.push(new_dataArray[i]);
    };
};

alert(result);
alexl
  • 6,841
  • 3
  • 24
  • 29
  • For efficiency, you should `break;` after setting `isInOldArray = true;` - there's no point in continuing through the loop after a match has been found. – daiscog Sep 29 '11 at 12:38
  • 1
    No problem. In fact, it can be made more efficient still by `continue`ing the outer loop when a match is found and thus removing the need to set, and later check, a boolean. And then we get ... my solution! :-) – daiscog Sep 29 '11 at 12:47
  • This solution works for my small sample array. But for some reason, it doesn't work with a full json object. Maybe I should rephrase. How can I compare 2 json objects deep recursively and return an Array of all changed items ? – Mikou Sep 29 '11 at 16:50