【问题标题】:Removing elements from an array of objects based on duplicate values of multiple keys根据多个键的重复值从对象数组中删除元素
【发布时间】:2016-06-27 05:02:30
【问题描述】:

我有一个这样的对象数组 -

var arr = [
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"false", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"true", quantity:4}
];

我想删除具有相同 type_idfull_empty 值的重复项。结果应该是这样的 -

var arr = [
    { type_id: "3", full_empty:"true", quantity:1},
    { type_id: "9", full_empty:"true", quantity:4},
    { type_id: "9", full_empty:"false", quantity:4},
];

我已经搜索并找到了一些解决方案,但其中一些是用于删除重复键或仅基于一个键的重复值来删除重复项。一些需要的外部库。还有一些我无法理解的解决方案。有没有简单的方法在纯 JavaScript 中做到这一点?

编辑以便更好地理解 - 我已阅读此 question 。该问题的公认答案是仅查找一个键的重复项。就我而言,我必须找到多个键的重复项。

【问题讨论】:

  • @Rohit416 我已尝试实施该解决方案。但它只在一个键中搜索重复值。就我而言,我必须在多个键中搜索重复值。
  • 但是如果数组是var arr = [ { type_id: "3", full_empty:"true", quantity:1}, { type_id: "3", full_empty:"true", quantity:2}, ... ];你期望什么结果?

标签: javascript filter


【解决方案1】:

您可以使用纯函数,通过使用 Array.some()Array.reduce() 将输入数组缩减为不同元素的数组,如下所示

    var arr = [
        { type_id: "3", full_empty:"true", quantity:1},
        { type_id: "3", full_empty:"true", quantity:1},
        { type_id: "9", full_empty:"true", quantity:4},
        { type_id: "9", full_empty:"false", quantity:4},
        { type_id: "9", full_empty:"true", quantity:4},
        { type_id: "9", full_empty:"true", quantity:4},
        { type_id: "9", full_empty:"true", quantity:4}
    ];

    var a = arr.reduce(function (accumulator, current) {
      if (checkIfAlreadyExist(current)) {
        return accumulator
      } else {
        return accumulator.concat([current]);
      }
      
      function checkIfAlreadyExist(currentVal) {
        return accumulator.some(function(item){
          return (item.type_id === currentVal.type_id &&
                  item.full_empty === currentVal.full_empty);
        });
      }
    }, []);
        
    console.log(a);

简洁的 ES6 语法

一个更简洁的reduce可以使用ES6箭头函数和展开操作符写成如下:

var arr = [
            { type_id: "3", full_empty:"true", quantity:1},
            { type_id: "3", full_empty:"true", quantity:1},
            { type_id: "9", full_empty:"true", quantity:4},
            { type_id: "9", full_empty:"false", quantity:4},
            { type_id: "9", full_empty:"true", quantity:4},
            { type_id: "9", full_empty:"true", quantity:4},
            { type_id: "9", full_empty:"true", quantity:4}
        ];

var a = arr.reduce((accumulator, current) => {
  if (checkIfAlreadyExist(current)) {
    return accumulator;
  } else {
    return [...accumulator, current];
  }

  function checkIfAlreadyExist(currentVal) {
    return accumulator.some((item) => {
      return (item.type_id === currentVal.type_id &&
              item.full_empty === currentVal.full_empty);
    });
  }
}, []);
            
console.log(a);

【讨论】:

  • 谢谢,您的回答解决了问题。许多答案都缺少一个关键点-如果有多个键,我必须搜索重复项。
  • @ni8mr 我的荣幸 :)。如果它适合你,请接受答案
【解决方案2】:

尽管有其他解决方案,我建议使用以type_idfull_empty 作为键的哈希表,如果找到新的,则将哈希设置为真。与Array#filter 一起,您将获得一个包含唯一项的新数组。

var arr = [{ type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "false", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }],
    filtered = arr.filter(function (a) {
        var key = a.type_id + '|' + a.full_empty;
        if (!this[key]) {
            this[key] = true;
            return true;
        }
    }, Object.create(null));

console.log(filtered);

ES6

var arr = [{ type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "false", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }],
    filtered = arr.filter(
        (temp => a =>
            (k => !temp[k] && (temp[k] = true))(a.type_id + '|' + a.full_empty)
        )(Object.create(null))
    );

console.log(filtered);

【讨论】:

    【解决方案3】:
    //To search the element is already exisit or not.(to remove Duplicate)
        function searchExisting(type_id,full_empty,newArray){
            for(var i=0;i<newArray.length;i++){
                if(newArray[i].type_id==type_id && newArray[i].full_empty==full_empty){
                    return true;
                }
            }
            return false;
        }
    
    //loop through every element and push it into new array
        var arr2=[];
        for(var i=0;i<arr.length;i++){
            if(!searchExisting(arr[i].type_id,arr[i].full_empty,arr2)){
                arr2.push(arr[i]);
            }
        }
        console.log(arr2)
    

    【讨论】:

    • 谢谢,您的回答也有帮助。
    【解决方案4】:

    您可以使用findforEach 从该数组中创建一个包含重复值的新数组

    希望这个 sn-p 有用

    var arr = ["Json Array object as supplied in the question"];
    
    // A new array which will contain unique json object
    var newArray = [];
    
    //Loop through each of the object in the original array
    
    arr.forEach(function(item) {
        // If newArray .length is zero then just push the first element
        // else in newArray find if a json object already exist which have same
        // type_id & full_empty. If it does not exist it will return undefined
        if (newArray.length !== 0) {
            var _isPresent = newArray.find(function(secItem) {
                return secItem.type_id === item.type_id && secItem.full_empty === item.full_empty
            })
            // If element is not present then push this json pbject
            if (_isPresent == undefined) {
                newArray.push(item)
            }
        } else {  // this will execute only once when newArray length is 0
    
            newArray.push(item)
        }
    })
    console.log(newArray)
    

    JSFIDDLE

    【讨论】:

      【解决方案5】:

      这不像Ninas answer那么棒,但可以注意到和一个新的答案。

      var arr = [ { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "3", full_empty: "true", quantity: 1 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "false", quantity: 4}, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4 }, { type_id: "9", full_empty: "true", quantity: 4}];
      
      var dict = {}, result = [];
      
      arr.forEach((i, key) => {
        !dict[(key = i.type_id + i.full_empty)] 
            && (dict[key] = result.push(i));
      })
      console.log(result)

      【讨论】:

        【解决方案6】:

        数组对象上有过滤器和映射。您可以使用过滤器来定位所需的非活动属性。它是一个布尔评估,返回一个“过滤”的新数组。

        这是Egghead.IO 网站上发布的一个很棒的视频教程,它真正分解了它。

        【讨论】:

          【解决方案7】:

          如果你不想进入代码,那么你可以使用下面的 sn-p :-

          var sDat = [
          { sid:12, scode:"code", sname:"Deep" },
          { sid:12, scode:"code", sname:"Anand" },
          { sid:139, scode:"code", sname:"Singh"}
          ];
          
          function cleanup(arr, prop) {
          var new_arr = [];
          var lookup  = {};
          
          for (var i in arr) {
              lookup[arr[i][prop]] = arr[i];
          }
          
          for (i in lookup) {
              new_arr.push(lookup[i]);
          }
          
          return new_arr;
          }
          
          var n = cleanup(sDat, 'sid');
          alert(n);
          

          我希望这对你有用。

          【讨论】:

          • 它可以工作,但使用您的代码,我只能在一个键的情况下检查重复值。如果有多个键,我需要一次这样做。顺便说一句,谢谢。
          【解决方案8】:

          这是我修改后的Aditya Singh's answer

          var arr = [
                          { type_id: "3", full_empty:"true", quantity:1},
                          { type_id: "3", full_empty:"true", quantity:1},
                          { type_id: "9", full_empty:"true", quantity:4},
                          { type_id: "9", full_empty:"false", quantity:4},
                          { type_id: "9", full_empty:"true", quantity:4},
                          { type_id: "9", full_empty:"true", quantity:4},
                          { type_id: "9", full_empty:"true", quantity:4}
                      ];
          
          
              var a = arr.reduce((accumulator, current) => {
          
               const isAlreadyExist = accumulator.some(item => (
                item.type_id === currentVal.type_id && item.full_empty === currentVal.full_empty
               ))
          
               return isAlreadyExist(current) ? accumulator : [...accumulator, current];
              }, []);
          
              console.log(a);
          

          【讨论】:

            【解决方案9】:

            var arr = [
                { type_id: "3", full_empty:"true", quantity:1},
                { type_id: "3", full_empty:"true", quantity:1},
                { type_id: "9", full_empty:"true", quantity:4},
                { type_id: "9", full_empty:"false", quantity:4},
                { type_id: "9", full_empty:"true", quantity:4},
                { type_id: "9", full_empty:"true", quantity:4},
                { type_id: "9", full_empty:"true", quantity:4}
            ];
            
            let op = [];
            
            arr.forEach((el) => {
              if (isNotExist(el)){
                op.push(el)
              }
              function isNotExist(obj){
                return op.every(el => JSON.stringify(el) !== JSON.stringify(obj) )
              	
              }
            })
            
            console.log(op)

            【讨论】:

              猜你喜欢
              • 2017-09-18
              • 2020-04-03
              • 2015-05-13
              • 1970-01-01
              • 2017-05-02
              • 1970-01-01
              • 2011-05-26
              • 1970-01-01
              相关资源
              最近更新 更多