我在比较两个数组时遇到问题。一个是固定数据集,而另一个是动态生成的。
两个数组的样本如下:
// 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”数组中的每个对象。
因此,例如,如果匹配数组与上面的示例相同,它将两次记录不匹配的国家/地区列表,其中比利时记录为“匹配”,另一次记录比利时为不匹配的国家(加纳相同但反转明显)。
我只想让它记录一次不匹配的国家名单,这就是全部。
我希望这是一个简单的疏忽,但无法弄清楚。提前谢谢。
答案 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.every
和Array.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"}]
答案 3 :(得分:0)
将matches
列表中的所有名称放入哈希作为键:
var index = {}; 火柴。 forEach(name =&gt; index [name] = true;)
遍历countries
并检查index
中是否存在当前的一个:
for(让国家/地区) if(!index.hasOwnProperty(country.name)) console.log(country.name,&#39;未包含&#39;);
得到O(N + M)而不是O(N * M)