簡體   English   中英

如何按名稱相似但不相同的對象數組進行分組

[英]How to group by an array of objects with similar names but not the same

我有這種類型的對象數組:

  [{
    ID: 'MCHARPENT ',
    REA: 4,
    STO: 90,
    EFFCAR: 178,
  },
  {
    ID: 'I050MCHE  ',
    REA: 0,
    STO: 125,
    EFFCAR: 228,
  },
  {
    ID: 'I050MCHE  ',
    REA: 0,
    STO: 106,
    EFFCAR: 231,
  },
  {
    ID: 'DBALLAVOINE',
    REA: 0,
    STO: 107,
    EFFCAR: 172,
  },
  {
    ID: 'DBALLAVOINE',
    REA: 20,
    STO: 30,
    EFFCAR: 100,
  }]

當 ID 為:

  • 相同的(第二個和第三個對象)
  • 或者當一個以 'I050' 之后的 3 個字母開頭時,如在本例中為字母 'MCH',它是第一個 ID 的開頭,在第二個 ID 的 I050 之后

如果匹配,則不帶“I050”的 ID 將取代名稱。 此外,我必須對其他值求和。

使用這四個對象的結果應該如下所示:

  {
    ID: 'MCHARPENT',
    REA: 4,
    STO: 321,
    EFFCAR: 637,
  },
  {
    ID: 'DBALLAVOINE',
    REA: 20,
    STO: 137,
    EFFCAR: 272,
  }]

我無法找到一種方法來滿足這些條件。

沒有進行任何排序,因為幸運的是給定的示例不需要它。 這可能是一個問題,具體取決於您獲得的數據數組。

 let results = []; let something = 'I050'; let items = [{ID: 'MCHARPENT ',REA: 4,STO: 90,EFFCAR: 178,},{ID: 'I050MCHE ',REA: 0,STO: 125,EFFCAR: 228,},{ID: 'I050MCHE ',REA: 0,STO: 106,EFFCAR: 231,},{ID: 'DBALLAVOINE',REA: 0,STO: 107,EFFCAR: 172,}]; items.forEach( item => { if (item.ID.startsWith(something)) { results.filter( result => { if (result.ID.startsWith(item.ID.trim().slice(4, -1))) { result.REA = result.REA + item.REA; result.STO = result.STO + item.STO; result.EFFCAR = result.EFFCAR + item.EFFCAR; } // could do an ELSE here pushing the item to results so it doesn't get lost if there is no match }); } else { results.push(item); } }); console.log(results);

這是使用.sort() ( Documentation ) 和.reduce() ( Documentation ) 的一種方法

首先,我們對對象進行排序以將所有'I050' ID 放在最后(因為它們可能需要折疊到我們需要首先創建的現有對象中)

然后,我們減少結果並組合符合要求的對象。

 const data = [{ID: 'MCHARPENT ', REA: 4, STO: 90, EFFCAR: 178}, {ID: 'I050MCHE ', REA: 0, STO: 125, EFFCAR: 228}, { ID: 'I050MCHE ', REA: 0, STO: 106, EFFCAR: 231}, { ID: 'DBALLAVOINE', REA: 0, STO: 107, EFFCAR: 172 }] const result = data // Move all of the 'I050' IDs to the end.sort(obj => obj.ID.startsWith('I050')? 1: -1) // Combine the data.reduce((acc, curr) => { // Find any existing object we would want to merge this into const existingObj = acc.find(obj => // Has the same ID obj.ID === curr.ID || // Or, if this is an 'I050', starts with the next 3 chars (curr.ID.startsWith('I050') && obj.ID.startsWith(curr.ID.substring(4, 7)))) // If we find an object, merge them if (existingObj) { existingObj.REA += curr.REA existingObj.STO += curr.STO existingObj.EFFCAR += curr.EFFCAR } else { // If not, just add this as a new object acc.push(curr) } // Return the new array return acc }, []) console.log(result)

這里有 2 個簡單for循環

 const data = [ { ID: 'MCHARPENT ', REA: 4, STO: 90, EFFCAR: 178, }, { ID: 'I050MCHE ', REA: 0, STO: 106, EFFCAR: 231, }, { ID: 'I050MCHE ', REA: 0, STO: 125, EFFCAR: 228, }, { ID: 'DBALLAVOINE', REA: 0, STO: 107, EFFCAR: 172, }]; const groupedData = []; function canBeMerged(item1, item2){ if(item1.ID == item2.ID) return true; let item1ID = item1.ID.substring(4, 7); let item2ID = item2.ID.substring(0, 3); if(item1ID == item2ID) return true; item2ID = item2.ID.substring(4, 7); item1ID = item1.ID.substring(0, 3); if(item1ID == item2ID) return true; return false; } function merge(group, datapoint){ group.REA += datapoint.REA; group.STO += datapoint.STO; group.EFFCAR += datapoint.EFFCAR; } for(let i = 0; i < data.length; i++){ if(i === 0){ groupedData.push(data[i]); continue; } let added = false; for(let j = 0; j < groupedData.length; j++){ if(canBeMerged(groupedData[j], data[i])){ merge(groupedData[j], data[i]); added = true; continue; } } if(added === false) groupedData.push(data[i]); } console.log(groupedData)

編輯 1:添加 function 以檢查合並條件。

暫無
暫無

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

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