简体   繁体   English

如何按名称相似但不相同的对象数组进行分组

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

I have this type of array of objects:我有这种类型的对象数组:

  [{
    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,
  }]

I'm searching a way to group them when the IDs are:当 ID 为:

  • either the same (second and third objects)相同的(第二个和第三个对象)
  • or when one starts with 3 letters that are found after 'I050', as in this case the letters 'MCH', which is the beginning of the first ID and is after I050 in the second或者当一个以 'I050' 之后的 3 个字母开头时,如在本例中为字母 'MCH',它是第一个 ID 的开头,在第二个 ID 的 I050 之后

If there is a match, the ID without 'I050' take over the name.如果匹配,则不带“I050”的 ID 将取代名称。 In addition, I have to sum the other values.此外,我必须对其他值求和。

The result should look like this with these four objects:使用这四个对象的结果应该如下所示:

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

I don't manage to find a way to group by with these conditions.我无法找到一种方法来满足这些条件。

Haven't done any sorting because luckely for the given example it is not needed.没有进行任何排序,因为幸运的是给定的示例不需要它。 This could be a problem depending on the array of data you are getting.这可能是一个问题,具体取决于您获得的数据数组。

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

Here is one approach using .sort() ( Documentation ) and .reduce() ( Documentation )这是使用.sort() ( Documentation ) 和.reduce() ( Documentation ) 的一种方法

First, we sort the objects to put all 'I050' IDs at the end (since they may need to be collapsed into existing objects that we need to create first)首先,我们对对象进行排序以将所有'I050' ID 放在最后(因为它们可能需要折叠到我们需要首先创建的现有对象中)

Then, we reduce down the results and combine the objects where they match the requirements.然后,我们减少结果并组合符合要求的对象。

 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)

Here 2 simple for loops这里有 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)

EDIT 1: function added to check the merge condition.编辑 1:添加 function 以检查合并条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM