【问题标题】:Error in applying array filter in array with multiple objects在具有多个对象的数组中应用数组过滤器时出错
【发布时间】:2018-08-25 21:21:16
【问题描述】:

目前我正在做一个 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" }); 

但是,当我在控制台中测试条件时,它会返回以下内容:

 [{…}, {…}, {…}]

同时,我看到有一个类似的答案。但不同的是,它使用负选择,当有不匹配的东西时返回 false,如下所示:

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" });

这次成功了。

所以我想知道的是,我在第一个脚本上的错误是什么? 如果我仍然想使用积极的标准,即只返回符合这两个标准的案例,我该怎么做? 非常感谢

【问题讨论】:

    标签: javascript arrays array-filter


    【解决方案1】:

    在您的原始函数中,您总是从filter 回调中返回true,因此没有任何内容被过滤掉。

    但是,您也应该能够过滤并使用 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}))
    // []

    【讨论】:

    • 秒杀我,干得好!顺便说一句,obj[key] &amp;&amp; 是完全不必要的,如果属性是 0false、... 等,它可能会导致问题:whatIsInAName([{"a": 0}, {"a": 0, "b": 1}], {"a": 0})
    【解决方案2】:

    您的原始代码不起作用,因为只要属性符合条件,您就会返回true。它不会继续检查其余的键。

    例如成像x{ a: 1, b: 2 }source{ a: 1, b: 1}。您的原始代码检查属性a,它匹配,所以truefilter 返回。它不会继续检查b 是否匹配(因为return 会立即终止函数)。

    第二个代码示例完全相反,一旦找到不匹配的属性,它就会停止检查属性(如果一个属性不匹配,那么检查其余的将是多余的)。

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

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

    【讨论】:

    • 嗨易卜拉欣,这简直太棒了,真的很有帮助!还有一个问题:据我所知,过滤器将扫描数组中的所有元素。在我一直理解这一点之前,在这种情况下它只会扫描数组中的所有对象,但过滤器确实会扫描每个对象中的键和属性?
    • @PakHangLeung filter 确实扫描了整个数组,但您的函数应该扫描对象。 filter 循环遍历数组并在数组中的每个对象上调用您为它提供的函数,然后查看该函数调用是否产生 truefalse 以决定是否应包含该对象。 filter 不知道函数做什么也不关心,它只关心它的返回值。在您的原始代码中,您传递给 filter 的函数不起作用,它只是检查(传入对象的)至少一个键是否匹配以返回 true
    猜你喜欢
    • 1970-01-01
    • 2018-10-25
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    相关资源
    最近更新 更多