Prashobh
Prashobh

Reputation: 9542

Compare array and remove unmatched values

$scope.locations = [
    { name : "One"},
    { name : "Two"},
    { name : "Three"},
    { name : "India"},
    { name : "Japan"},
    { name : "China"}
];

$scope.tempLocations = [
    { name : "One"},
    { name : "Two"},
    { name : "global"},
];

I have two arrays. If location doesn't contain some of the names in tempLocations I want to remove them from tempLocation. In this case i want to remove location Global

I tried the following, but does not work.

for(var i=0;i<$scope.tempLocations.length;i++){
    var index = $scope.tempLocations.indexOf($scope.locations[i]);
    if(index == -1){
        console.log($scope.tempLocations[i]);
        $scope.tempLocations.splice(i,1);
    }
}

Upvotes: 0

Views: 2208

Answers (3)

Brad Wells
Brad Wells

Reputation: 429

If $scope.locations isn't going to change often, you could do the following:

Build a lookup table for locations

var location_lookup = {};
for ( var i = 0; i < $scope.locations.length; i++ ) {
    location_lookup[$scope.locations[i].name] = true;
}

Filter based on the existence of a key

$scope.filteredLocations = $scope.tempLocations.filter(function(temp) {
    return location_lookup.hasOwnProperty(temp.name);
});

This will prove to be much faster if you're filtering more often than you need to recompute the lookup. So if $scope.locations is static, this would be a good route.

I would advise against using temp.name in location_lookup as another poster said to since that will also check ALL of the prototyped properties of the location_lookup object. For instance, if another script in your app did Object.prototype.global = function(){} then the filter would return "global" as being part of $scope.locations, which is not the behavior you want. hasOwnProperty will only check the object itself and not any prototypical inheritance while also being a more efficient method.

Fiddle Demonstration: http://jsfiddle.net/cu33ojfy/ (also included an implementation that uses Array.prototype to add a .filter_locations() method, but adding to Array.prototype is generally a bad idea)

Upvotes: 1

georg
georg

Reputation: 214969

I guess you're looking for this

$scope = {}

$scope.locations = [
    { name : "One"},
    { name : "Two"},
    { name : "Three"},
    { name : "India"},
    { name : "Japan"},
    { name : "China"}
];

$scope.tempLocations = [
    { name : "One"},
    { name : "Two"},
    { name : "global"},
];
$scope.tempLocations = $scope.tempLocations.filter(function(x) {
     return $scope.locations.some(function(y) {
          return x.name == y.name
     })
})

document.getElementById("output").innerHTML = JSON.stringify($scope.tempLocations, 0,' ');
console.log($scope);
<pre id="output"></pre>

If you have many (100+) locations, consider converting them to an "associative array" first, like:

validLocations = { "One": 1, "Two": 1 ... etc

Upvotes: 3

xec
xec

Reputation: 18024

You need to loop through manually as the comment from Paul S. suggests:

var locations = [
  { name : "One"},
  { name : "Two"},
  { name : "Three"},
  { name : "India"},
  { name : "Japan"},
  { name : "China"} ];

var tempLocations = [
  { name : "One"},
  { name : "Two"},
  { name : "global"},
];

var newTempLocations = tempLocations.filter(function(temp){
  return locations.some(function(location){ // stop and return true at first match
    return location.name === temp.name;
  });
})

// print output
document.getElementById("output").innerHTML = JSON.stringify(newTempLocations, null, "  ");
<pre id="output"></pre>

Upvotes: 2

Related Questions