簡體   English   中英

在JavaScript中使用帶有reduce的map來過濾數組中的對象

[英]Using map with reduce in javascript to filter objects in an array

freecodecamp有一個問題,詳細信息如下:

需求:
使一個函數遍歷對象數組(第一個參數)並返回具有匹配的名稱和值對的所有對象的數組(第二個參數)。

例如,如果第一個參數是[{first:“ Romeo”,last:“ Montague”},{first:“ Mercutio”,last:null},{first:“ Tybalt”,last:“ Capulet”}],並且第二個參數是{last:“ Capulet”},則必須從數組中返回第三個對象(第一個參數),因為它包含名稱和其值,該對象作為第二個參數傳遞。

預期結果:

whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" }) should return [{ first: "Tybalt", last: "Capulet" }].

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 }].

並且根據站點,有這樣的解決方案:

function whatIsInAName(collection, source) {
  var srcKeys = Object.keys(source);

  // filter the collection
  return collection.filter(function (obj) {
    return srcKeys
      .map(function(key) {
        return obj.hasOwnProperty(key) && obj[key] === source[key];
      })
      .reduce(function(a, b) {
        return a && b;
      });
  });
}

// test here
whatIsInAName([{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }], { last: "Capulet" });

在此解決方案中,有一件事我不太了解,那就是map函數的返回值。

在我的期望中,map函數將循環遍歷所有鍵和值對以檢查其是否匹配,並返回具有布爾值的數組,即[[true,false},{false,false}]等,然后將布爾值傳遞給reduce函數。

但是,當我使用以下腳本測試map函數時:

var source = { last: "Capulet" };
var collection = [{ first: "Romeo", last: "Montague" }, { first: "Mercutio", last: null }, { first: "Tybalt", last: "Capulet" }];
var srcKeys = Object.keys({ last: "Capulet" });

collection.filter(function(obj){
  return srcKeys.map(function(key){
    return obj.hasOwnProperty(key) && obj[key] === source[key];
  })
})

回報是這樣的

(3) [{…}, {…}, {…}]
 0: {first: "Romeo", last: "Montague"}
 1: {first: "Mercutio", last: null}
 2: {first: "Tybalt", last: "Capulet"}
 length: 3
  __proto__: Array(0)

在這種情況下,我有2個問題:

  1. 在map函數中,它將創建一個新數組,並在調用數組中的每個元素上調用提供的函數。 在這種情況下,由於我們只想返回符合條件的元素,為什么它不返回布爾值或只返回具有匹配值的元素,而是返回所有值? 還是我對映射功能有誤解?

  2. 在map函數之后的reduce函數中,它如何獲取映射的布爾值到單個布爾值,該布爾值指示所有srcKeys是否都通過上述條件? 例如,在這種情況下,reduce函數是否簡單地獲取map的返回值並進一步進行計算?

非常感謝您的提前幫助!

如我所說,功能map不是必需的。

可以使用函數filter用函數沿着every為了過濾那些匹配的鍵值對對象(第二PARAM),該對象。

 let whatIsInAName = (arr, obj) => arr.filter(o => Object.keys(obj).every(k => obj[k] === o[k])); console.log(whatIsInAName([{ "apple": 1, "bat": 2 }, { "bat": 2 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "bat": 2 })); console.log(whatIsInAName([{ "first": "Romeo", "last": "Montague" }, { "first": "Mercutio", "last": null }, { "first": "Tybalt", "last": "Capulet" }], { "last": "Capulet" })); console.log(whatIsInAName([{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }], { "apple": 1, "cookie": 2 })); console.log(whatIsInAName([{ "apple": 1, "bat": 2 }, { "apple": 1 }, { "apple": 1, "bat": 2, "cookie": 2 }, { "bat":2 }], { "apple": 1, "bat": 2 })); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

map部分將source所有鍵值對映射到一個布爾數組,該布爾數組指示值是否在obj中:

 var obj = { a: 1, c: 3 };
 var source = { a: 1, b: 2, c: 3 };

 var mapped = Object.keys(source).map(key => obj[key] === source[key]);

 console.log(mapped); // [true, false, true]

現在,該數組不能用作直接過濾的返回值,因為數組總是真實的,而不管是什么。 現在,reducer將該數組轉換為一個布爾值,如下所示:

 [true, false, true].reduce((a, b) => a && b) // false

是相同的:

 true && false && true // false

因此,如果所有鍵值均存在,則最后返回true。


PS:停止此過程,建議的代碼很糟糕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM