web-dev-qa-db-fra.com

Ajouter uniquement des objets uniques à un tableau en JavaScript

Disons que je commence par ceci:

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"
                            }];

J'utilise ceci pour pré-remplir un formulaire. Les utilisateurs peuvent modifier des entrées ou en ajouter de nouvelles. Je dois les empêcher d'ajouter des doublons.

Le problème est que la structure du formulaire que je sérialise et l'ordre dans lequel ces valeurs sont renvoyées de la base de données ne sont pas les mêmes. Il est donc possible que j'insère un élément dans ce tableau au format suivant:

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

Ce qui est identique à la première entrée, vient d’être commandé différemment.

Je charge des underscorejs, alors s’il est possible de gérer cela avec cette bibliothèque, ce serait génial. J'utilise aussi jQuery si cela aide.

À ce stade, je ne sais pas comment procéder.

16
S16

La fonction Underscore findWhere fait exactement ce dont vous avez besoin - ce n'est pas une recherche indexOf par identité d'objet, mais recherche des objets dont les propriétés ont les mêmes valeurs que l'entrée.

if (_.findWhere(shippingAddresses, toBeInserted) == null) {
    shippingAddresses.Push(toBeInserted);
}
28
Bergi

Exemple de base utilisant lodashunion 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>

Bien que cela ne réponde pas directement à la question, cela répond à la question plus générale de savoir comment ajouter des valeurs uniques à un tableau, et comme moi, d'autres pourraient tomber sur cette page de Google.

14
vsync

sur la base de cette réponse à: "js-remove-an-array-element-by-index-in-javascript"

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

J'utilise l'idiome suivant qui est concis et ne nécessite pas underscore.js ou tout autre framework.

Voici un exemple d’enregistrement de lignes sélectionnées et non sélectionnées pour DataTables jquery plugin . Je conserve un tableau des identifiants actuellement sélectionnés et je ne souhaite pas avoir de doublons dans le tableau:

en 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)

Plus généralement ce serait

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

ou en JS

var position;

position = myArray.indexOf(myval);

if (!~position) {
  myArray.Push(myVal);
}
3
Ashley Raiteri

EDIT, cela fonctionnera avec votre exemple de propriétés non triées:

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});

et nous pourrions faire cela avec un one-liner mais ce serait super laid:

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});
1
Matthew Graves

Si vous voulez vérifier l'objet d'entrée utilisateur, vous pouvez essayer cette fonction:

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");
        }
    });
}

Et essayez d’appeler cette fonction de vérification dans un paramètre différent (uniqueInput et duplicatedInput).

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

Je fais un jsfiddle . Vous pouvez l'essayer… .. espérons que cela vous soit utile.

1
Chickenrice

Exemple de base utilisant Set() à partir de ECMAScript 2015

L'objet Set vous permet de stocker des valeurs uniques de tout type (qu'il s'agisse de valeurs primitives ou de références d'objet). Si un objet iterable est passé, tous ses éléments seront ajoutés à la nouvelle Set. Ici, je vais juste ajouter une valeur:

// Use Set to remove duplicate elements from the array 
// and keep your new addition from causing a duplicate
const numbers = [1, 1, 1, 2, 3, 100]

// existing value is not added since it exists (and array is de-duped)
console.log(Array.from(new Set([...numbers, 100])))
// [1, 2, 3, 100]

// non-existing value is added (and array is de-duped)
console.log(Array.from(new Set([...numbers, 101])))
// [1, 2, 3, 100, 101]

0
Paul Sturm