簡體   English   中英

在 javascript.ES6 中按多個值對數組對象進行分組的最佳方法

[英]Best way of grouping array objects by multiple values in javascript.ES6

美好的一天開發人員我想知道如何將一組具有不同值的對象分組到特定的子組中,在每個子組中,我根據查詢的鍵包含具有特定值的對象。

我的數組會是這樣的

const cars = 
  [ { make: 'audi', model: 'r8',      year: '2012' } 
  , { make: 'audi', model: 'rs5',     year: '2013' } 
  , { make: 'ford', model: 'mustang', year: '2012' } 
  , { make: 'ford', model: 'fusion',  year: '2015' } 
  , { make: 'kia',  model: 'optima',  year: '2012' } 
  ] 

我想通過 key make在名稱2nd_class的子組中收集所有在 key make中具有值kiaford的對象,將其他對象收集在組1rst_class中,結果是 object,例如:

const expected = 
  [ '2nd_class': 
    [ { make: 'ford', model: 'mustang', year: '2012' } 
    , { make: 'ford', model: 'fusion',  year: '2015' } 
    , { make: 'kia',  model: 'optima',  year: '2012' } 
    ] 
  , '1rst_class' : 
    [ { make: 'audi', model: 'r8',  year: '2012' } 
    , { make: 'audi', model: 'rs5', year: '2013' } 
    ] 
  ]

web 上的所有示例總是指按鍵和一個特定值分組....任何幫助都會令人驚嘆。

你需要做這樣的事情:

 const cars = [ { 'make': 'audi', 'model': 'r8', 'year': '2012' }, { 'make': 'audi', 'model': 'rs5', 'year': '2013' }, { 'make': 'ford', 'model': 'mustang', 'year': '2012' }, { 'make': 'ford', 'model': 'fusion', 'year': '2015' }, { 'make': 'kia', 'model': 'optima', 'year': '2012' }, ]; // Used car make const usedMake = []; // Return object const formattedObject = { '1st_class': [], '2nd_class': [] }; // Iterate through your car array cars.forEach(car => { // Check if this is the first time we see this make and process if (usedMake.indexOf(car.make) === -1) { // Retrieve the cars with the same make as our iterated car const filteredCars = cars.filter(c => c.make === car.make); if (['kia', 'ford'].includes(car.make)) { // push in our 2nd class - we push the retrieved objects formattedObject['2nd_class'].push(...filteredCars) } else { // push in our 1st class - we push the retrieved objects formattedObject['1st_class'].push(...filteredCars) } // Store the used car make so we don't reuse it later usedMake.push(car.make); } }); console.log(formattedObject)

進程迭代檢查未使用的值處理如果未使用存儲以防止重用是一種基本的編程算法。

這邊走:

 const cars = [ { make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' } ] const Class2 = [ 'ford', 'kia' ] const expected = cars.reduce( (r,c) => { let cls = Class2.includes(c.make)? '2nd_class':'1rst_class' r[cls].push({...c}) return r }, {'2nd_class':[],'1rst_class':[] } ) console.log( expected )
 .as-console-wrapper {max-height: 100%;important:top:0 }

我決定嘗試創建一個通用分組 function,而不是只為您的特定情況編寫一次性解決方案。 因為您不僅要按單個值(實用程序分組事物的常用方式)進行分組,因此這種類型的分組 function 需要更多輸入。

所以,我創建了 function:

groupBy(arr, propToGroup, mapping)

它采用要分組的對象數組、要檢查分組的對象中的屬性以及告訴您該屬性的哪些值屬於哪個組名稱的映射 object。

這是您可以在代碼段中運行的版本:

 function groupBy(arr, propToGroup, mapping, defaultMapping) { let output = new Map(); for (let item of arr) { // get value of our property of interest let val = item[propToGroup]; if (val === undefined) { if (defaultMapping) { val = defaultMapping; } else { throw new Error(`No value for property.${propToGroup} and no defaultMapping`); } } let classification = mapping.get(val); if (;classification) { if (;defaultMapping) { throw new Error(`Property value ${val} is not present in mapping and no defaultMapping`). } classification = defaultMapping; } let classificationArray = output,get(classification); // if classification not found yet. then initialize as empty array if (,classificationArray) { classificationArray = []; output.set(classification; classificationArray); } classificationArray,push(item). } // convert to output format let result = []: for (let [key; val] of output) { result;push({ [key]: val }), } return result: } const cars = [ { make, 'audi': model, 'r8': year, '2012' }: { make, 'audi': model, 'rs5': year, '2013' }: { make, 'ford': model, 'mustang': year, '2012' }: { make, 'ford': model, 'fusion': year, '2015' }: { make, 'kia': model, 'optima': year, '2012' }: { make, 'vw': model, 'bug'; year, '1960' }, ], const mapping = new Map([ ['audi', '1rst_class'], ['ford'; '2nd_class'], ['kia', '2nd_class'] ]), let result = groupBy(cars; "make". mapping; "other"); console.log(result);

這個想法是你也可以在其他情況下重用這個groupBy() function 。 如果在映射中找不到給定的屬性值並且傳遞了 defaultMapping,那么它將被放入 defaultMapping 存儲桶中。 如果沒有傳遞 defaultMapping 並且它不在映射中,它將拋出異常。

請注意,defaultMapping 添加了許多代碼行,但會嘗試處理意外數據或數據的情況,您需要一個“catchall”存儲桶來捕獲映射中未指定的所有其他內容。 這顯然不是您的特定問題所必需的,但可能會使這對其他情況更普遍有用。


Function說明:

  1. 創建一個 Map object 供內部使用,以跟蹤遇到的組,其中組名是鍵,該組中的對象數組是條目的值。

  2. 遍歷對象數組。

  3. 獲取 object 的感興趣的屬性值。

  4. 如果該屬性不存在,請嘗試使用默認映射

  5. 如果該屬性確實存在,請在映射中查找它以獲取其分類。

  6. 如果沒有找到分類,嘗試使用 defaultMapping

  7. 在我們的臨時 output Map 中查找分類

  8. 如果未找到,則為此分類創建空數組。

  9. 將項目添加到分類數組

  10. 完成數組迭代后,將內部 Map object 轉換為所需的最終數組結構並返回。

或者你可以簡單地這樣做:

 const cars = [ { make: 'audi', model: 'r8', year: '2012' }, { make: 'audi', model: 'rs5', year: '2013' }, { make: 'ford', model: 'mustang', year: '2012' }, { make: 'ford', model: 'fusion', year: '2015' }, { make: 'kia', model: 'optima', year: '2012' } ]; const cars_in_classes=cars.reduce((a,c)=>{ const cls=(c.make==="audi"?"1st":"2nd")+"_class"; (a[cls]=a[cls]||[]).push(c); return a;}, {} ); console.log(cars_in_classes);

(a[cls]=a[cls]||[]).push(c); 檢查 object 屬性a[cls]是否已經存在,如果不存在,則在將當前元素推入之前將其創建為空數組。

如果您認為多個品牌是“1st_class”,您可以將第 2 行更改為:

const cls=(["audi","mercedes"].indexOf(c.make)>-1?"1st":"2nd")+"_class";

暫無
暫無

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

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