在具有多个对象的数组中应用数组过滤器时发生错误

时间:2018-08-25 21:21:17

标签: javascript arrays array-filter

目前,我正在从事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" });

这一次有效。

所以我想知道的是,第一个脚本的错误是什么? 如果我仍然想使用肯定标准,即仅返回符合两个标准的个案,我该如何做呢? 非常感谢

2 个答案:

答案 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,它与之匹配,因此truefilter返回。不会继续检查b是否匹配(因为return立即终止功能)。

第二个代码示例执行的操作正好相反,一旦找到不匹配的属性,它将停止检查属性(如果一个属性不匹配,则检查其余属性将是多余的)。

原始代码:搜索符合条件的属性。如果找到一个,则返回true,如果找不到,则返回false。仅当所有键均不匹配时,此代码才会失败;如果至少一个键匹配,则此代码才会成功。

第二个代码:搜索不匹配的属性。如果找到一个,则返回false,如果找不到,则返回true。如果至少一个键不匹配,则此代码将失败;如果所有键都匹配,则此代码将成功。