使用AngularJS比较两个对象数组

时间:2015-06-29 21:38:22

标签: javascript arrays angularjs foreach nested-loops

我在比较两个数组时遇到问题。一个是固定数据集,而另一个是动态生成的。

两个数组的样本如下:

// Fixed list of 197 countries
$scope.countries = [
  {"name": "Afghanistan", "code": "AF"},
  {"name": "Albania", "code": "AF"},
  {"name": "Algeria", "code": "AF"},

  //...

  {"name": "Zimbabwe", "code": "ZW"}
];

//Dynamically generated list of matched countries

$scope.matches = [
  {"name": "Belgium"},
  {"name": "Ghana"}
];

在游戏结束时,将运行一个函数并对两个数组进行比较。截至目前,我已经尝试过(看起来像)使用angular.forEach和标准javascript循环进行此比较的几乎所有组合。当我尝试记录哪些国家/地区尚未匹配时,问题就出现了。

这是我正在运行的比较功能。

$scope.compareArrays = function(){
      angular.forEach($scope.countries, function(country,name){
        angular.forEach($scope.matches, function(match){
          if (country.name !== match.name) {
            console.log(country.name);
          } else {
            console.log("MATCHED");
          }
        });
      });
};

该功能将查找并记录未匹配的国家/地区...但它会多次记录整个不匹配国家/地区列表。特别是对于“matches”数组中的每个对象。

因此,例如,如果匹配数组与上面的示例相同,它将两次记录不匹配的国家/地区列表,其中比利时记录为“匹配”,另一次记录比利时为不匹配的国家(加纳相同但反转明显)。

我只想让它记录一次不匹配的国家名单,这就是全部。

我希望这是一个简单的疏忽,但无法弄清楚。提前谢谢。

4 个答案:

答案 0 :(得分:0)

你在这里做的是(伪代码):

for each existing country
    for each country to be matched
        log country.name UNLESS it's a match

问题是,即使所有现有国家 位于matches列表中,您现有的197个国家/地区 匹配其他196个。

您确实需要确保每个country(来自countries列表)与来自matches的国家/地区的 ANY 不匹配:然后和只有这样,它实际上是一个“无与伦比的”国家。

这是一个获取该列表的好方法(使用Underscore.js,我强烈推荐):

// Fixed list of 197 countries
var countries = [
  {"name": "Afghanistan", "code": "AF"},
  {"name": "Albania", "code": "AF"},
  {"name": "Algeria", "code": "AF"},
  {"name": "Zimbabwe", "code": "ZW"}
];

// Dynamically generated list of matched countries

var matches = [
  {"name": "Albania"},
  {"name": "Ghana"}
];

// Rejecting the countries that have "some" (at least one) match in the other list.
function compareArrays(countries, matches){
    return _.reject(countries, function(country) {
        return _.some(matches, function(match) {
            return country.name === match.name;
        });
    });
};

_.each(compareArrays(countries, matches), function(unmatched) {
    console.log(unmatched);
});

// Object {name: "Afghanistan", code: "AF"}
// Object {name: "Algeria", code: "AF"}
// Object {name: "Zimbabwe", code: "ZW"}

这是指向working JSFiddle的链接。

请注意,我没有在该答案中使用任何Angular内容,因为该问题实际上与算法有关。

答案 1 :(得分:0)

我猜你可以跳过计算重复检查,以某种方式启动当前第一个循环。我会用索引和for循环完成这个:

$scope.compareArrays = function(){
  var c = $scope.countries;
  var m = $scope.matches;
  for(var i = 0;i < c.length;i++) {
    for(var j = i;j < m.length;j++) { // Notice the j = i;
      if (c[i].name !== m[j].name) {
        console.log(c[i].name);
      } else {
        console.log("MATCHED");
      }
    };
  });
};

我希望这能回答你的问题,并希望你也喜欢普通的JS!

答案 2 :(得分:0)

你应该把它分解成更小的功能。例如,创建一个比较函数,如果true列表中没有country,则会返回matches

function isUnmatched(country, matches) {
  return matches.every(function(matched){
    return country.name !== matched.name;
  });
}

然后创建一个函数,为每个国家/地区调用isUnmatched并返回一系列不匹配的国家/地区:

function getUnmatched() {
  return countries.filter(function(country){
    return isUnmatched(country, matches);
  });
}

如果您的环境不支持Array.prototype.everyArray.prototype.filter,您可以按如下方式重写上述内容:

function isUnmatched(country, matches) {
  var i = matches.length;
  while (i--) {
    if (country.name === matches[i].name) {
      return false;
    }
  }
  return true;
}

function getUnmatched() {
  var unmatched = [],
      i = countries.length,
      country;

  while (i--) {
    country = countries[i];
    if (isUnmatched(country, matches)) {
      // console.log(country.name)
      unmatched.push(country);
    }
  }

  return unmatched;
}

因此,如果您的列表如下所示:

var countries = [
  {"name": "Afghanistan", "code": "AF"},
  {"name": "Albania", "code": "AF"},
  {"name": "Algeria", "code": "AF"}
];

var matches = [
  {"name": "Albania"},
  {"name": "Algeria"}
];

然后:

var unmatched = getUnmatched(); 
//=> [{"name": "Afghanistan", "code": "AF"}]

JSFiddle 1
JSFiddle 2

答案 3 :(得分:0)

  1. matches列表中的所有名称放入哈希作为键:

    var index = {};  火柴。 forEach(name =&gt; index [name] = true;)

  2. 遍历countries并检查index中是否存在当前的一个:

    for(让国家/地区)      if(!index.hasOwnProperty(country.name))          console.log(country.name,&#39;未包含&#39;);

  3. 得到O(N + M)而不是O(N * M)