Add only unique objects to an array in JavaScript

2019-02-06 00:33发布

Let's say I start with this:

var shippingAddresses =      [{
                                "firstname": "Kevin",
                                "lastname": "Borders",
                                "address1": "2201 N Pershing Dr",
                                "address2": "Apt 417",
                                "city": "Arlington",
                                "state": "VA",
                                "zip": "22201",
                                "country": "US"
                            }, {
                                "firstname": "Dan",
                                "lastname": "Hess",
                                "address1": "304 Riversedge Dr",
                                "address2": "",
                                "city": "Saline",
                                "state": "MI",
                                "zip": "48176",
                                "country": "US"
                            }];

I use this to prepopulate a form. Users can edit entries or add new ones. I need to prevent them from adding duplicates.

The issue is that the structure of the form that I am serializing and the order these values are returned from the database are not the same, so there is a chance that I will insert an item into this array with the following format:

                            {
                                "country": "US",
                                "firstname": "Kevin",
                                "lastname": "Borders",
                                "address1": "2201 N Pershing Dr",
                                "address2": "Apt 417",
                                "zip": "22201",                                    
                                "city": "Arlington",
                                "state": "VA"
                            }

Which is the same as the first entry, just ordered differently.

I am loading underscorejs, so if there's a way to handle it with that library that would be great. I'm also using jQuery if that helps.

At this point I'm not sure how to proceed.

5条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-02-06 00:53

Basic example using lodash union method:

var a = [1,2,3];

// try to add "1" and "4" to the above Array
a = _.union(a, [1, 4]);

console.log(a);
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>

While this doesn't directly answers the question, it does answers the broader question of how to add unique values to an Array, and like myself, others might stumble upon this page from google.

查看更多
孤傲高冷的网名
3楼-- · 2019-02-06 00:59

EDIT, this will work with your example of unsorted properties:

var normalized_array = _.map(shippingAddresses, function(a){ 
      var o = {}; 
      _.each(Object.keys(shippingAddresses[0]), function(x){o[x] = a[x]});
      return o;
})
var stringy_array = _.map(normalized_array, JSON.stringify);
shippingAddresses = _.map(_.uniq(stringy_array), JSON.parse});

and we could do this with a one-liner but it would be super ugly:

shippingAddresses_uniq = _.map(_.uniq(_.map(_.map(shippingAddresses, function(a){ var o = {}; _.each(Object.keys(shippingAddresses[0]), function(x){o[x] = a[x]}); return o; }), JSON.stringify)), JSON.parse});
查看更多
\"骚年 ilove
4楼-- · 2019-02-06 01:07

The Underscore findWhere function does exactly what you need - it's not an indexOf search by object identity, but searches objects whose properties have the same values as the input.

if (_.findWhere(shippingAddresses, toBeInserted) == null) {
    shippingAddresses.push(toBeInserted);
}
查看更多
Lonely孤独者°
5楼-- · 2019-02-06 01:08

If you want to check the user input object you could try this function:

var uniqueInput = {
                       "country": "UK",
                       "firstname": "Calvin",
                       "lastname": "Borders",
                       "address1": "2201 N Pershing Dr",
                       "address2": "Apt 417",
                       "city": "Arlington",
                       "state": "VA",
                       "zip": "22201"

                        };

var duplicatedInput = {
                       "country": "US",
                       "firstname": "Kevin",
                       "lastname": "Borders",
                       "address1": "2201 N Pershing Dr",
                       "address2": "Apt 417",
                       "city": "Arlington",
                       "state": "VA",
                       "zip": "22201"

                        };

var shippingAddresses = [{
                       "firstname": "Kevin",
                       "lastname": "Borders",
                       "address1": "2201 N Pershing Dr",
                       "address2": "Apt 417",
                       "city": "Arlington",
                       "state": "VA",
                       "zip": "22201",
                       "country": "US"
                        }, {
                            "firstname": "Dan",
                            "lastname": "Hess",
                            "address1": "304 Riversedge Dr",
                            "address2": "",
                            "city": "Saline",
                            "state": "MI",
                            "zip": "48176",
                            "country": "US"
                        }];

function checkDuplication(checkTarget,source){
    _.each(source,function(obj){
        if(_.isEqual(checkTarget,obj)){ 
            alert("duplicated");
        }
    });
}

And try to invoke this check function in different parameter (uniqueInput and duplicatedInput) I think it could check the duplication input in your shipping addresses.

checkDuplication(uniqueInput,shippingAddresses);
checkDuplication(duplicatedInput,shippingAddresses);

I make a jsfiddle. You could try it. Hope this is helpful for you.

查看更多
forever°为你锁心
6楼-- · 2019-02-06 01:11

based on this answer to: "js-remove-an-array-element-by-index-in-javascript"

https://stackoverflow.com/a/7142909/886092

I'm using the following idiom that is concise and does not require underscore.js or any other framework.

Here is an example for recording selected and deselected rows for DataTables jquery plugin. I keep an array of currently selected ids, and I don't want to end up with duplicates in the array:

in coffeescript

  fnRowSelected: (nodes) ->
    position = $selected.indexOf(nodes[0].id)
    unless ~position
      $selected.push nodes[0].id
    return
  fnRowDeselected: (nodes) ->
    position = $selected.indexOf(nodes[0].id)
    if ~position
      $selected.splice(position, 1)

More generally it would

position = myArray.indexOf(myval)
unless ~position
  myArray.push myVal

or in JS

var position;

position = myArray.indexOf(myval);

if (!~position) {
  myArray.push(myVal);
}
查看更多
登录 后发表回答