0

I have two JavaScript array's. For every item in first array, I need to check if that items exists in second array and if does, I should remove that item from second array. I do not want to create another array. At the end of the process I should have second array with the correct values. With below code I am not able to get the desired result.

var arr = [1, 2, 3];

var childArr = [1, 2, 3, 4, 51, 2, 3, 5];

for (var i = 0; i < arr.length; i++) {
    for (var j = 0; j < childArr.length; j++) {
        if (childArr[j] === arr[i]) {
            childArr.splice(childArr[j], 1);
        }
    }
}
10
  • Why don't you want to create another array? That would be much easier. var difference = childArr.filter(function(e) { return arr.indexOf(e) === -1; }); Commented May 9, 2014 at 13:47
  • 1
    The length of childArr will be decreased by one when you splice it, right? So you should do to j what? Commented May 9, 2014 at 13:48
  • Underscore difference or without are designed specifically for this. If underscore is available to you! Commented May 9, 2014 at 13:48
  • @JLRishe: I know I can do it with another array. Just wanted to check if there is a way without another array. Commented May 9, 2014 at 13:49
  • 1
    :)) Teemu was actually SUGGESTING something. Commented May 9, 2014 at 13:50

4 Answers 4

4

You are trying to create an implementation of "array difference" algorithm, which could be easily rewritten with Array.prototype.filter method:

[1, 2, 3, 4, 51, 2, 3, 5].filter(function(c) {
    return [1, 2, 3].indexOf(c) < 0;
}); // [4, 51, 5]
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for reply. using indexOf is not a good option as I need to support IE 8. I forgot to mention that in my question.
@Brown_Dynamite For both filter and indexOf methods there are polyfills, that you may apply to support old browsers. Or if you use jQuery use $.grep and $.inArray methods correspondingly.
This doesn't meet OP's stated requirement of modifying the original array and not creating a new array. I already demonstrated pretty much this same approach in the comments 3 minutes before you posted this answer.
@JLRishe Oh, it is good that you also know about it, nothing unique in this approach really. I was thoroughly waiting until someone posts it as an answer. Personally I don't see any requirements about that in the question: the OP's comment states that he knows how to do it with another array, which mostly refers to smth like arr = []; for ... if (...) arr.push(...);. However, this solution was not good for the OP because of compatibility issues (which obviously can be bypassed). And don't forget that the OP may be wrong with his concerns about new arrays: there is nothing bad in it.
The question text says "I should remove that item from second array. I do not want to create another array." (emphasis added) OP may indeed be mistaken with his/her concerns about new arrays, but s/he already knows how to accomplish this by creating a new array and that's not what the question was about.
|
0

Your issue is because when you splice a member from the array, it's length is shorter and the members are moved one lower, so you skip the next member. The simple solution is to iterate over the array being spliced in reverse.

Also, you need to splice j, not childArr[j].

var arr = [1, 2, 3];

var childArr = [1, 2, 3, 4, 51, 2, 3, 5];

for (var i = 0; i < arr.length; i++) {
    for (var j = childArr.length; j >=0; j--) {
        if (childArr[j] === arr[i]) {
            childArr.splice(j, 1);
        }
    }
}

console.log(childArr); // [4, 51, 5]

A while loop can also be used:

for (var i = 0; i < arr.length; i++) {
    var j = childArr.length;
    while (j--) {
        if (childArr[j] === arr[i]) {
            childArr.splice(j, 1);
        }
    }
}

Comments

0

How about this one? It's a little lengthy, but it handles the case where you have multiple occurrences of the values to remove. It also doesn't use indexOf.

var arr = [1, 2, 3];

var childArr = [1, 2, 3, 4, 51, 2, 3, 5];


for (var i = 0; i < arr.length;) {
    var foundInChildIndex = null;
    for (var j = 0; j < childArr.length; j++) {
        if (childArr[j] === arr[i]) {
            foundInChildIndex = j;
            break;
        }
    }
    if (foundInChildIndex != null) {
        childArr.splice(foundInChildIndex, 1);
    } else {
        i++;
    }
}

Comments

0

You have got a small typo:

var arr = [1, 2, 3];
var childArr = [1, 1, 2, 3, 4, 51, 2, 3, 5];
for (var i = 0; i < arr.length; i++) {
   for (var j = 0; j < childArr.length; j++) {
       if (childArr[j] === arr[i]) {
           childArr.splice(j--, 1); // <-- pass index only.
       }
   }
}

4 Comments

If there are repeated values in childArr to be removed, the above will skip some and leave them in the array. Try childArr = [1, 1, 2, 5].
@RobG It should right? Values of arr are compare to the full set of values in childArr. It is not doing a break. Although suitable answers have been provided, your comment has put in my interest. Have I missed something?
Yes, you missed something. In [1,1,2,5], when the value at index 0 is spliced, the member at index 1 is moved to index 0, index 2 to 1, and so on. The next member visited is at index 1 and has value 2, so the value 1 moved to index 0 remains when it should be removed.
@RobG Got it. Edited my answer. That's what iterators are for in other languages.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.