【问题标题】:filter array of object based on multiple properties基于多个属性过滤对象数组
【发布时间】:2018-08-17 05:28:49
【问题描述】:

tl;博士

我试图对不一定相同的对象数组进行重复数据删除。

描述。

我从一个管理不善的网站下载了一组记录,并且有许多重复的记录,尽管有些名称不同或权重不同。 id 喜欢做的是将每条记录与其他记录进行比较,并删除除权重最大的条目之外的所有条目,或者如果存在完全重复的条目(包括名称),则删除除一个条目之外的所有条目。

Arr 对象

{
      "entry"   : "Single Lift",
      "name"    : "Jane Doe",
      "sex"     : "female",
      "division": "40-44",
      "equipped": "raw",
      "wtclass" : 66,
      "lift"    : "bench press",
      "weight"  : 151
  }

function dedupe(lift=records){
    console.log(lift.length)
    lift.forEach((record,index)=>{
      for(i=0;i<lift.length;i++){
        if(record.sex===lift[i].sex){
          if(record.division===lift[i].division){
            if(record.equipped===lift[i].equipped){
              if(record.wtclass===lift[i].wtclass){
                if(record.entry===lift[i].entry){
                  if(record.name===lift[i].name&&record.weight===lift[i].weight) lift.splice(i,1)
                  else if(record.weight>lift[i].weight) lift.splice(i,1)
                  else if(record.weight<lift[i].weight) lift.splice(index,1)
                }
              }
            }
          }
        }
      }
    })
    console.log(lift.length)
    return lift
  }

这段代码显然没有按照我想要的方式运行,但它说明了意图。我想通过比较 entry sex division equipped wtclasslift 的任何条目的权重来删除除最大权重之外的所有权重(或除所有键:值相同的权重之外的所有权重)是匹配的。

关于对对象数组进行重复数据删除还有其他问题,但我找不到任何符合我的场景或我可以适应为我工作的东西。如果有人有解决方案(或解决方案的链接),我将不胜感激!

【问题讨论】:

  • 你能做的最好的就是声明一个空数组。然后遍历您拥有的数据并推送对象(如果它们尚不存在于空数组中)。如果它们存在,请检查重量是否更大并更换。等等。忘记你写的这个如果地狱
  • 我有点不清楚,你是说你想为每个“除了体重”的重复项找到所有个人最好成绩吗?因为如果是这样,yBrodsky 的评论将是正确的。
  • 我的问题是一些电梯被输入了两次完全重复(不难处理),而且当记录被打破时,有时旧记录没有被删除,所以会有两个相同的记录具有不同的权重值。我只想以最大的重量保持给定的记录。我现在正在根据 yBrodsky 的建议开发一个新功能,但我也对下面回答的 reduce 选项感兴趣,虽然我不熟悉 reduce
  • Ele 代码的快速复制粘贴肯定可以完成,虽然我不明白它做得很好。不过这对我来说很好,至少我有一些有用的东西,并且可以开始谷歌搜索以了解我所看到的!谢谢大家的帮助!
  • @Ele ...哇。那其实也更漂亮!

标签: javascript arrays node.js filter


【解决方案1】:

使用这些值,您可以连接它们并检查重复项。

您可以使用函数reduce

这个例子有两个具有相同值(但权重)的对象和一个具有不同值的对象。

var array = [
  {
    'entry': 'Single Lift',
    'name': 'Jane Doe',
    'g': 'f',
    'division': '40-44',
    'equipped': 'raw',
    'wtclass': 66,
    'lift':
    'bench press', 'weight': 151
  },
  {
    'entry': 'Single Lift',
    'name': 'Jane Doe',
    'g': 'f',
    'division': '40-44',
    'equipped': 'raw',
    'wtclass': 66,
    'lift': 'bench press',
    'weight': 160
  },
  {
    'entry': 'Single Lift', 
    'name': 'Ele', 
    'g': 'm', 
    'division': '40-44', 
    'equipped': 'raw', 
    'wtclass': 66, 
    'lift': 'bench press', 
    'weight': 151
  }
]

var result = Object.values(array.reduce((a, o) => {
  var {
    entry, 
    name, 
    g, 
    division, 
    equipped, 
    wtclass, lift
  } = o
  
  var key = [
    entry, 
    name, 
    g, 
    division, 
    equipped, 
    wtclass, 
    lift
  ].join('||')

  if (!a[key] || o.weight > a[key].weight) {
    a[key] = o
  }

  return a
}, {}))

console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案2】:

    const array = [
      { "entry"   : "Single Lift", "name"    : "Jane Doe", "sex"     : "female", "division": "40-44", "equipped": "raw", "wtclass" : 66, "lift"    : "bench press", "weight"  : 151 }, { "entry"   : "Single Lift", "name"    : "Jane Doe", "sex"     : "female", "division": "40-44", "equipped": "raw", "wtclass" : 66, "lift"    : "bench press", "weight"  : 152 }, { "entry"   : "Single Lift", "name"    : "Jane Doe", "sex"     : "female", "division": "40-44", "equipped": "raw", "wtclass" : 66, "lift"    : "bench press", "weight"  : 151 }, { "entry"   : "Double Lift", "name"    : "Jane Doe", "sex"     : "female", "division": "40-44", "equipped": "raw", "wtclass" : 66, "lift"    : "bench press", "weight"  : 151 }
    ]
    
    const groupBy = (xs, exceptions) => 
       xs.reduce((groups, element) => {
         var key = Object.assign({}, element);
         for (let i = 0; i < exceptions.length; i++) {
           delete key[exceptions[i]];
         }
         key = Object.values(key).join(',');
               
         if (!groups[key]) {
            groups[key] = [element];
         } else {
            groups[key].push(element);
         }
    
         return groups;
       }, {})
    
    let grouppedRecords = groupBy(array, ['weight']);
    
    let biggestWeightRecords = Object.values(grouppedRecords).map(records => {
      let biggestWeightRecord = records[0];
      for (let i = 0; i < records.length; i++) {
        if (records[i].weight > biggestWeightRecord.weight) {
          biggestWeightRecord = records[i];
        }
      }
      return biggestWeightRecord;
    });
    
    console.log(biggestWeightRecords);

    【讨论】:

      【解决方案3】:

      具有 2 次迭代的解决方案,允许过滤任意数量的属性,两个规则(更大和更小),如果过滤器属性的值是原始值,则仅适用。

      const elements = [
          {
              foo: 1,
              bar: 2,
              fooBard: 3,
          },
          {
              foo: 2,
              bar: 2,
              fooBard: 6,
          },
          {
              foo: 1,
              bar: 2,
              fooBard: 5,
          },
          {
              foo: 2,
              bar: 2,
              fooBard: 3,
          }
      ];
      
      const RULE_BIGGER = 'RULE_BIGGER';
      const RULE_SMALLER = 'RULE_SMALLER';
      
      const elementsFiltered = new Map();
      
      const createKey = (element, ...matchingProperties) =>
          matchingProperties
          .map(matchProperty => element[matchProperty] || '')
          .join('#');
      
      
      const hasToBeUpdated = (rule) => (oldValue, newValue) => {
          switch (rule) {
              case RULE_BIGGER:
                  return newValue > oldValue;
              case RULE_SMALLER:
                  return newValue < oldValue;
              default:
                  return false;
          }
      }
      
      const filterByProperty = (elements, property, rule, ...matchingProperties) => {
          const hasToBeUpdatedWithRule = hasToBeUpdated(rule);
          elements.forEach((element) => {
              const key = createKey(element, ...matchingProperties);
              const storedElement = elementsFiltered.get(key)
              if (!storedElement ||
                  hasToBeUpdatedWithRule(storedElement[property], element[property])) {
                      elementsFiltered.set(key, element);
              }
          });
          const result = [];
          elementsFiltered.forEach(elementFiltered => {
              result.push(elementFiltered);
          });
          return result;
      };
      
      const result = filterByProperty(elements, 'fooBard', RULE_BIGGER, 'foo', 'bar');
      
      console.log(result);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-13
        • 1970-01-01
        • 1970-01-01
        • 2020-07-04
        • 1970-01-01
        • 2017-11-03
        • 1970-01-01
        • 2020-04-21
        相关资源
        最近更新 更多