目前,我正在从事JavaScript练习。
练习的目的是比较由不同对象形成的数组。该函数有2个参数:集合是主数组,来源是比较条件。仅返回主数组中包含与源数组相同的键和属性的对象。
结果应如下:
whatIsInAName(
[{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }],
{ last: "Capulet" }
) // should return [{ first: "Tybalt", last: "Capulet" }].
whatIsInAName(
[{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }],
{ "apple": 1 }
) // should return [{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }]
whatIsInAName(
[{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }],
{ "apple": 1, "bat": 2 }
) // should return [{ "apple": 1, "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }]
whatIsInAName(
[{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }],
{ "apple": 1, "cookie": 2 }
) // should return [{ "apple": 1, "bat": 2, "cookie": 2 }]
whatIsInAName(
[{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }, { "bat":2 }],
{ "apple": 1, "bat": 2 }
) // should return [{ "apple": 1, "bat": 2 }, { "apple": 1, "bat": 2, "cookie":2 }]
whatIsInAName(
[{"a": 1, "b": 2, "c": 3}],
{"a": 1, "b": 9999, "c": 3}
) // should return []
为解决这个问题,我使用了数组过滤器功能,目的是选择符合条件的对象并作为新数组返回。代码如下:
function whatIsInAName(collection, source) {
var arr = [];
var key = Object.keys(source)
return collection.filter(function(x){
for(var y = 0; y < key.length; y++){
if(x.hasOwnProperty(key[y]) && x[key[y]] == source[key[y]]){
return true;
}
}
return true;
})
}
whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
但是,当我在控制台中测试条件时,它将返回以下内容:
[{...},{...},{...}]
同时,我看到了类似的答案。但是不同之处在于,它使用否定选择,当某项不匹配时返回否定:
function whatIsInAName(collection, source) {
var srcKeys = Object.keys(source);
return collection.filter(function (obj) {
for(var i = 0; i < srcKeys.length; i++) {
if(!obj.hasOwnProperty(srcKeys[i]) || obj[srcKeys[i]] !== source[srcKeys[i]]) {
return false;
}
}
return true;
});
}
// test here
whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });
这一次有效。
所以我想知道的是,第一个脚本的错误是什么? 如果我仍然想使用肯定标准,即仅返回符合两个标准的个案,我该如何做呢? 非常感谢
答案 0 :(得分:3)
在原始功能不起作用的情况下,您总是从true
回调返回filter
,因此没有任何内容被过滤掉。
但是,您还应该可以过滤every
并将其与搜索对象的Object.keys
一起使用:
function whatIsInAName(arr, search_obj) {
return arr.filter(obj => Object.keys(search_obj)
.every(key => obj[key] === search_obj[key]))
}
console.log(whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" }))
// [{ first: "Tybalt", last: "Capulet" }].
console.log(whatIsInAName([{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }], { "apple": 1 }))
// [{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }]
console.log(whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 }))
// [{ "apple": 1, "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }]
console.log(whatIsInAName([{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "cookie": 2 }))
// [{ "apple": 1, "bat": 2, "cookie": 2 }]
console.log(whatIsInAName([{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }, { "bat":2 }], { "apple": 1, "bat": 2 }))
// [{ "apple": 1, "bat": 2 }, { "apple": 1, "bat": 2, "cookie":2 }]
console.log(whatIsInAName([{"a": 1, "b": 2, "c": 3}], {"a": 1, "b": 9999, "c": 3}))
// []
答案 1 :(得分:1)
您的原始代码无效,因为一旦属性符合条件,您将返回true
。它不会继续检查其余的键。
例如,成像x
是{ a: 1, b: 2 }
,而source
是{ a: 1, b: 1}
。您的原始代码检查了属性a
,它与之匹配,因此true
从filter
返回。不会继续检查b
是否匹配(因为return
立即终止功能)。
第二个代码示例执行的操作正好相反,一旦找到不匹配的属性,它将停止检查属性(如果一个属性不匹配,则检查其余属性将是多余的)。
原始代码:搜索符合条件的属性。如果找到一个,则返回true
,如果找不到,则返回false
。仅当所有键均不匹配时,此代码才会失败;如果至少一个键匹配,则此代码才会成功。
第二个代码:搜索不匹配的属性。如果找到一个,则返回false
,如果找不到,则返回true
。如果至少一个键不匹配,则此代码将失败;如果所有键都匹配,则此代码将成功。