lodash/underscore; compare two objects and remove duplicates

白昼怎懂夜的黑 提交于 2020-01-13 11:24:26

问题


As you can see in the image below, I have some returned json data with three objects; each contains a clients id => data.

exact_match : {104}
match_4 :  {104, 103}
match_2 :  {104, 103, 68}

How can I "trim" or remove the duplicate objects based on previous ones? something like:

exact_match : {104}
match_4 :  {103}
match_2 :  {68}

I tried _.difference but did not work (Maybe because it is for arrays not objects?):

var exact_match = data.exact_match,
    match_four_digits = _.difference(data.match_4, data.exact_match),
    match_two_digits = _.difference(data.match_2, data.exact_match, data.match_4),

Any help would be appreciated :)

Update

I need that the returned value has the same object data instead of a new array :)


回答1:


It looks like you want to diff keys (or rather, it'd be efficient to — _.keys)

_.difference(
  _.keys({104: 1, 102: 3, 101: 0}), // ["104", "102", "101"]
  _.keys({104: 1, 102: 3}) // ["104", "102"]
)
// [ "101" ]

Or, you could always convert your object to an array of pairs if you want to compare within the objects too (_.pairs):

_.difference(
  _.pairs({104: 1, 102: 3, 101: 0}), // [["104",1], ["102",3], ["101",0]]
  _.pairs({104: 1, 102: 2}) // [["104",1], ["102",2]]
)
// [["102", 3], ["101", 0]]



回答2:


I would create a map called unique, e.g. var unique = {}; and then iterate over each key in your data and check if it's in unique. If it is in unique, delete the entry associated with that key, thus removing duplicates.

You could pull this check out as an alreadyFound method:

var alreadyFound = function (key) {
  if (!(key in unique)) {
    unique[key] = true;
    return false;
  }
  return true;
};

Then iterate over your data and check alreadyFound(key) for key in your data, and delete the key if alreadyFound(key) returns true.

You could go messing with lodash/underscore methods but those might be inefficient depending on how you use them (and how they're implemented) and this should operate in linear time.

It looks like for your specific use case the full solution would be something like:

var unique = {};
// Assume I copy and pasted alreadyFound here
var alreadyFound = ...;
for (var object in data) {
  // Iterate through ids in each object in data
  for (var id in object) {
    // Remove this entry if it's already found
    if (alreadyFound(id)) {
      delete object[id];
    }
  }
}



回答3:


Thanks guys for the answers, I really appreciate your time.

I searched further and found this post by Lodash developer that helped me came up with this snippet;

var data = {
  exact_match: {
    104: {
      supplier_id: 104
    }
  },
  match_four_digits: {
    104: {
      supplier_id: 104
    },
    68: {
      supplier_id: 68
    }
  },
  match_two_digits: {
    104: {
      supplier_id: 104
    },
    68: {
      supplier_id: 68
    },
    103: {
      supplier_id: 103
    },
    999: {
      supplier_id: 999
    }
  }
};

var arr_match_four_digits = _.difference(_.keys(data.match_four_digits), _.keys(data.exact_match));
var arr_match_two_digits = _.difference(_.keys(data.match_two_digits), _.keys(data.match_four_digits), _.keys(data.exact_match));



$('#output1').html(JSON.stringify(data));
$('#output2').html(JSON.stringify(_.pick(data.match_four_digits, arr_match_four_digits)));
$('#output3').html(JSON.stringify(_.pick(data.match_two_digits, arr_match_two_digits)));
<script src="https://cdn.rawgit.com/lodash/lodash/3.3.1/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

data
<pre><code><div id="output1"></div></code></pre>
arr_match_four_digits
<pre><code><div id="output2"></div></code></pre>
match_two_digits
<pre><code><div id="output3"></div></code></pre>


来源:https://stackoverflow.com/questions/28858853/lodash-underscore-compare-two-objects-and-remove-duplicates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!