【问题标题】:How to get the difference between two arrays but keeping repeat objects如何获得两个数组之间的差异但保持重复对象
【发布时间】:2017-08-30 00:23:00
【问题描述】:

假设您有两个包含对象的数组,Array 1Array 2。我遇到的问题是找到两个数组之间的 exact 差异,其中可能包括看似相等的元素。在这个例子中,我注释了每个数组中的具体对象。

您可以将其视为有一个包含重复商品的购物车,但您只能兑换一件商品。所以//number 4 是重复项之一,但在Array 3

中仍然需要它

阵列 1

[
  { // number 1
    item_id: 4,
    total_price: 2.71
  },
  { // number 2
    item_id: 2,
    total_price: 3.71
  },
  { // number 3
    item_id: 4,
    total_price: 1.71
  },
  { // number 4
    item_id: 4,
    total_price: 2.71
  }
]

阵列 2

[
  { // number 1
    item_id: 4,
    total_price: 2.71
  }
]

我如何找到这两个数组之间的区别,Array 3?最好在每个对象上都有一个唯一的键以便更容易比较?在 javascript/node 中执行此操作,主要使用 lodash。

阵列 3

[
  { // number 2
    item_id: 2,
    total_price: 3.71
  },
  { // number 3
    item_id: 4,
    total_price: 1.71
  },
  { // number 4
    item_id: 4,
    total_price: 2.71
  }
]

【问题讨论】:

  • 我不明白为什么“数字 4”在结果数组中?元素索引是否也算作差异?
  • @sboesch 我编辑了这个问题,但考虑到这一点,假设您有一个包含重复商品的购物车,但您只能兑换一件商品。所以//number 4 是重复项之一,但在 Array 3 中仍然需要它
  • 对不起,但是什么?那么您实际上想要实现什么......如果两个数组中都存在相同的对象,请将其从结果数组中删除?
  • @KornholioBeavis 见上文 :)

标签: javascript arrays node.js lodash


【解决方案1】:

您可以遍历 Array1 并检查每个条目是否存在于 Array2 中,如果不存在于 Array3 中。

代码类似于:

for (var elt : array1) {
   var eltFound = false;
   var i = 0;

   // Loops in array2 to find element
   while (!eltFound && i < array2.length) {
      if (array2[i] == elt) { // maybe here do the check with item_id <-> elt[0]
         eltFound = true;
      }
   }

   if (!eltFound) {
      array3.push(elt);
   }
}

【讨论】:

    【解决方案2】:

    你可以用 lodash 来做这样的事情:

    array2.forEach(el => {
      let index = _.findIndex(array1, e => e.item_id === el.item_id);
      if (index >= 0) {
        array1.splice(index, 1);
      }
    });
    

    现在您的array1 将删除正确的值。如果您想保留原始的array1,请先将其复制并处理副本:

    let array3 = _.clone(array1);
    array2.forEach(el => {
      let index = _.findIndex(array3, e => e.item_id === el.item_id);
      if (index >= 0) {
        array3.splice(index, 1);
      }
    });
    

    现在您在array3 中获得了结果。

    【讨论】:

      【解决方案3】:

      仅在 JS 中,我宁愿使用slice 并逐个踢项目:

      for(var i = 0 ; i < array1.length ; i++) {
        for(var j = 0 ; j < array2.length ; j++) {
          if(array1[i].item_id == array2[j].item_id && array1[i].total_price == array2[j].total_price) {
            array1.splice(i,1);
            array2.splice(j,1);
            i--;
            j--;
            break;
          }
        }
      }
      console.log(array1);
      

      array1 现在包含来自差异的值。我刚刚用你的数据进行了测试,它可以工作。

      【讨论】:

        【解决方案4】:

        所以基本上你想从 Array1 中减去 Array2?

        有点难看,但它有效:

        for(var i = 0; i < arrayA.length; i++) {
            var arrAElement = arrayA[i];
        
            arrayC.push(arrAElement);
        
            for(var j = 0; j < arrayB.length; j++) {
                var arrBElement = arrayB[j];
        
                if(arrAElement.item_id == arrBElement.item_id && 
                   arrAElement.total_price == arrBElement.total_price) {
                    arrayB.splice(j,1);
                    arrayC.pop();
                    break;
                }
            }
        }
        

        工作演示: https://jsfiddle.net/a0180jdf/

        【讨论】:

          【解决方案5】:

          你可以这样做;

          function removeDupes(a){
            var hash = a.reduce(function(h,o){
                                  var k = Object.keys(o).reduce((p,c) => "" + o[p] + o[c]);
                                  h[k] || (h[k] = o);
                                  return h;
                                },{});
            return Object.keys(hash)
                         .map(k => hash[k]);
          }
          
          var data = [
            { // number 1
              item_id: 4,
              total_price: 2.71
            },
            { // number 2
              item_id: 2,
              total_price: 3.71
            },
            { // number 3
              item_id: 4,
              total_price: 1.71
            },
            { // number 4
              item_id: 4,
              total_price: 2.71
            }
          ],
           result = removeDupes(data);
           console.log(result);

          【讨论】:

            【解决方案6】:

            如果要保留原点arr1 的值,可以使用_.cloneDeep(arr1)

            var arr1 = [{ // number 1
                item_id: 4,
                total_price: 2.71
            }, { // number 2
                item_id: 2,
                total_price: 3.71
            }, { // number 3
                item_id: 4,
                total_price: 1.71
            }, { // number 4
                item_id: 4,
                total_price: 2.71
            }];
            
            let arr2 = [{ // number 1
                item_id: 4,
                total_price: 2.71
            }];
            
            // Loops through `arr2` and compare each element with `arr1`
            arr2.forEach(el2 => arr1.every((el1, index) =>
                // Compare `el2` with every `el1` in `arr1`
                // If `el2` === `el1`, return true to continue every loop
                // Otherwise, splice it out from the curren `index` and return false
                // to stop the every loop.
                el1.item_id !== el2.item_id || el1.total_price !== el2.total_price ? 
                true : arr1.splice(index, 1) && false
            ));
            
            console.log(arr1);

            【讨论】:

              【解决方案7】:

              这是使用lodash#differenceWith 的解决方案。

              function difference(arr1, arr2) {
                var found = {};
                return _.differenceWith(arr1, arr2, function(x, y) {
                  var isDiff = _.isEqual(x, y) && !found[x.id];
                  found[x.id] = true;
                  return isDiff;
                });
              }
              

              var array1 = [
                { // number 1
                  item_id: 4,
                  total_price: 2.71
                },
                { // number 2
                  item_id: 2,
                  total_price: 3.71
                },
                { // number 3
                  item_id: 4,
                  total_price: 1.71
                },
                { // number 4
                  item_id: 4,
                  total_price: 2.71
                }
              ];
              
              var array2 = [
                { // number 1
                  item_id: 4,
                  total_price: 2.71
                }
              ];
              
              function difference(arr1, arr2) {
                var found = {};
                return _.differenceWith(arr1, arr2, function(x, y) {
                  var isDiff = _.isEqual(x, y) && !found[x.id];
                  found[x.id] = true;
                  return isDiff;
                });
              }
              
              console.log(difference(array1, array2));
              body &gt; div { min-height: 100%; top: 0 }
              &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"&gt;&lt;/script&gt;

              【讨论】:

              • 最干净代码的最佳答案!!最后,我了解到找到具有唯一标识符的两个数组之间的差异是要走的路:)
              猜你喜欢
              • 1970-01-01
              • 2018-05-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-07-12
              • 2014-05-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多