0

I have two array with records like below:

var cars = ["Saab", "Volvo", "BMW"]; 

var cars1 = ["Saab", "Volvo", "BMW"]; 

Now I want to remove matching element from Cars1 so at the end my Cars1 array will be like below :

var cars = ["Saab", "Volvo", "BMW"]; 

var cars1 = ["Saab", "Volvo", "BMW"]; 

 for (var i = 0; i < cars1.length; i++) {
                for (var j = 0; j < cars.length; j++) {
                    if (cars1[i] == cars[j]) {
                        cars1.splice(i, 1);
                        break;
                    }
                }
            }
console.log(cars1)

Expected Output :

 var cars1 = []; 

I am not getting expected output.

1
  • I don't like the fact that most answers here aren't even trying to understand OP's bug. Commented Feb 28, 2017 at 14:08

5 Answers 5

3

Using a simple functional approach to save some space and make it cleaner I would recommend using Array.prototype.filter in combination with Array.prototype.indexOf like this:

var cars = ["Saab", "Volvo", "BMW"]; 

var cars1 = ["Saab", "Volvo", "BMW", "VW"];

cars1 = cars1.filter(car => cars.indexOf(car) < 0)

console.log(cars1)

The filter method calls the passed callback for each element, if the callback returns false the element won't be returned if returned true the element gets returned. Notice that the filter method returns a new array, and does not modify the current one! Thanks to @denys-séguret for mentioning it!

indexOf returns the index of the passed element. If not found -1 is returned. Thats why whe filter all elements out, where the index is < 0, only returning elements that are not already in the cars array.

Sign up to request clarification or add additional context in comments.

3 Comments

Please note this important difference: the original array isn't updated. It may matter, depending on OP's need (arrays are often shared). You also don't explain OP's bug.
Yes! Thats why I'm reassigning cars1 to the return value of the filter call.
Yes but this isn't enough when the array is shared (which is the most usual reason for using splice)
2

You're missing some items because the deleted item is replaced with the next one when you iterate. Just loop the other way, with i decreasing:

var cars = ["Saab", "Volvo", "BMW"]; 

var cars1 = ["Saab", "Volvo", "BMW"]; 

 for (var i=cars1.length; i--;) {
                for (var j = 0; j < cars.length; j++) {
                    if (cars1[i] == cars[j]) {
                        cars1.splice(i, 1);
                        break;
                    }
                }
            }
console.log(cars1)

Note that you don't really need an explicit double loop. One of the possible alternatives would be to use indexOf. Another one (more efficient in case of big arrays) would be to put the content of cars1 into an instance of Set. And if you don't need to keep the same array, there's also filter of course.

Here's how it would be with a set and reduce (a very efficient solution when cars arrays are big):

var cars = ["Saab", "Volvo", "BMW"]; 
var cars1 = ["Saab", "Volvo", "BMW"];
 
var set = cars.reduce((s,c) => s.add(c), new Set);
cars1 = cars1.filter(c => !set.has(c)); 
console.log(cars1);

And for antique browsers:

var cars = ["Saab", "Volvo", "BMW"]; 
var cars1 = ["Saab", "Volvo", "BMW"];
 
var set = cars.reduce(function(s,c){
     s[c] = true;
     return s;
}, Object.create(null));
cars1 = cars1.filter(function(c){
     return !set[c];
}); 
console.log(cars1);

8 Comments

Upvoted for your kind efforts towards helping me.I am having 1000 of records in both array so what do you think which approach will be more suitable??
@Learning In this case use the set. I'll update to show you how to do it
Sorry to bug you again but this set and reduce works in all browser and also old browser??
Starting from IE11. It must be slightly adapted to cover older versions of Internet Explorer. Do you want to see that version too ? (edit: done)
An instance of Set, or an plain object used as a set, is optimized for looking at properties by name. The default structure behind is a hash table and it's further optimized by good engines like V8, especially when it's reused.
|
1

The thing you are trying to do is called difference. The opposite is intersection.

var cars = ["Saab", "Volvo", "BMW", "Skoda"]; 

var cars1 = ["Saab", "Volvo", "BMW"]; 

function diff(arr1, arr2) {
  return arr1.filter(x => arr2.indexOf(x) === -1)
}

function intersec(arr1, arr2) {
  return arr1.filter(x => arr2.indexOf(x) > -1)
}

console.log(
  diff(cars, cars1),
  intersec(cars, cars1)
);

Comments

1

You are getting wrong result, because with every slice(), elements inside are changing their index. So after the first loop, Volvo will get 0 index and actually item with 0 index was already processed, so the function won't operate it. That's why it stays inside after function.

I suggest you to use Array#filter.

var cars = ["Saab", "Volvo", "BMW"],
    cars1 = ["Saab", "Volvo", "BMW"]; 
    
    var result = cars.filter(v => cars1.indexOf(v) == -1);
    console.log(result);

Comments

0

After the first call to cars1.splice(i, 1), the cars1 has one less element, hence it doesn't make much sense to continue with the outer loop. To make the code cleaner I`d suggest to use indexOf instead of the inner loop.

var cars = ["Saab", "Volvo", "BMW"];
var cars1 = ["Saab", "Volvo", "BMW"];

for (var i = 0; i < cars.length; i++) {
  var carPositionInCars1 = cars1.indexOf(cars[i]);
  if (carPositionInCars1 != -1) {
    cars1.splice(carPositionInCars1, 1);
  }
}
console.log(cars1);

1 Comment

Pplease provide some information on what your code actually does. Where did you improve the OPs code, what did he do wrong... it is hard to learn just from a few random lines of code that are thrown towards you without any explanation.

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.