web-dev-qa-db-fra.com

fonction jQuery pour obtenir tous les éléments uniques d'un tableau?

jQuery.unique vous permet d'obtenir des éléments uniques d'un tableau, mais la documentation indique que la fonction est principalement destinée à un usage interne et ne fonctionne que sur des éléments DOM. Une autre réponse SO a indiqué que la fonction unique() fonctionnait sur les nombres, mais que ce cas d'utilisation n'était pas nécessairement à l'épreuve du temps futur, car ce n'est pas explicitement indiqué dans la documentation.

Compte tenu de cela, existe-t-il une fonction "standard" de jQuery permettant d’accéder uniquement aux valeurs uniques - en particulier aux primitives telles que les entiers - dans un tableau? (Évidemment, nous pouvons construire une boucle avec la fonction each(), mais nous sommes nouveaux dans jQuery et aimerions savoir s’il existe une fonction jQuery dédiée à cela.)

66
Crashalot

Vous pouvez utiliser array.filter pour renvoyer le premier élément de chaque valeur distincte.

var a = [ 1, 5, 1, 6, 4, 5, 2, 5, 4, 3, 1, 2, 6, 6, 3, 3, 2, 4 ];

var unique = a.filter(function(itm, i, a) {
    return i == a.indexOf(itm);
});

console.log(unique);

Si la prise en charge de IE8 et des versions antérieures est principale, n'utilisez pas la méthode filter non prise en charge. 

Autrement,

if (!Array.prototype.filter) {
    Array.prototype.filter = function(fun, scope) {
        var T = this, A = [], i = 0, itm, L = T.length;
        if (typeof fun == 'function') {
            while(i < L) {
                if (i in T) {
                    itm = T[i];
                    if (fun.call(scope, itm, i, T)) A[A.length] = itm;
                }
                ++i;
            }
        }
        return A;
    }
}
115
kennebec

Utilisez simplement ce code comme base d’un simple plugin JQuery.

$.extend({
    distinct : function(anArray) {
       var result = [];
       $.each(anArray, function(i,v){
           if ($.inArray(v, result) == -1) result.Push(v);
       });
       return result;
    }
});

Utilisez comme tel:

$.distinct([0,1,2,2,3]);
46
js1568

Basé sur la réponse de @ kennebec, mais corrigé pour IE8 et inférieur en utilisant des wrappers jQuery autour du tableau pour fournir les fonctions de tableau manquantes filter et indexOf:

Le wrapper $ .makeArray () n'est peut-être pas absolument nécessaire, mais vous obtiendrez des résultats étranges si vous omettez ce wrapper et JSON.stringify le résultat autrement.

var a = [1,5,1,6,4,5,2,5,4,3,1,2,6,6,3,3,2,4];

// note: jQuery's filter params are opposite of javascript's native implementation :(
var unique = $.makeArray($(a).filter(function(i,itm){ 
    // note: 'index', not 'indexOf'
    return i == $(a).index(itm);
}));

// unique: [1, 5, 6, 4, 2, 3]
13
Dennis

Je voudrais utiliser underscore.js , qui fournit une méthode uniq qui fait ce que vous voulez.

9
lawnsea
    // for numbers
    a = [1,3,2,4,5,6,7,8, 1,1,4,5,6]
    $.unique(a)
    [7, 6, 1, 8, 3, 2, 5, 4]

    // for string
    a = ["a", "a", "b"]
    $.unique(a)
    ["b", "a"]

Et pour les éléments dom, aucun exemple n'est nécessaire ici, je suppose, car vous le savez déjà!

Voici le lien jsfiddle de l'exemple en direct: http://jsfiddle.net/3BtMc/4/

6
Rubyrider

Parcourez le tableau et poussez les éléments dans un hachage lorsque vous les rencontrez. Renvoyez le hachage pour chaque nouvel élément.

Notez que cela fonctionnera UNIQUEMENT correctement pour les primitives (chaînes, nombres, null, indéfini, NaN) et quelques objets qui se sérialisent sur la même chose (fonctions, chaînes, dates, éventuellement des tableaux dépendant du contenu). Les hachages dans ceci entreront en collision car ils se sérialiseront tous à la même chose, par exemple. "[objet Objet]"

Array.prototype.distinct = function(){
   var map = {}, out = [];

   for(var i=0, l=this.length; i<l; i++){
      if(map[this[i]]){ continue; }

      out.Push(this[i]);
      map[this[i]] = 1;
   }

   return out;
}

Il n'y a également aucune raison pour que vous ne puissiez pas utiliser jQuery.unique. La seule chose que je n'aime pas à ce sujet, c'est que cela détruit l'ordre de votre tableau. Voici le code exact si vous êtes intéressé:

Sizzle.uniqueSort = function(results){
    if ( sortOrder ) {
        hasDuplicate = baseHasDuplicate;
        results.sort(sortOrder);

        if ( hasDuplicate ) {
            for ( var i = 1; i < results.length; i++ ) {
                if ( results[i] === results[i-1] ) {
                    results.splice(i--, 1);
                }
            }
        }
    }

    return results;
};
6
Mark Kahn
function array_unique(array) {
    var unique = [];
    for ( var i = 0 ; i < array.length ; ++i ) {
        if ( unique.indexOf(array[i]) == -1 )
            unique.Push(array[i]);
    }
    return unique;
}
5
jaggedsoft

c'est la solution de js1568, modifiée pour fonctionner sur un tableau generic , comme:

 var genericObject=[
        {genProp:'this is a string',randomInt:10,isBoolean:false},
        {genProp:'this is another string',randomInt:20,isBoolean:false},
        {genProp:'this is a string',randomInt:10,isBoolean:true},
        {genProp:'this is another string',randomInt:30,isBoolean:false},
        {genProp:'this is a string',randomInt:40,isBoolean:true},
        {genProp:'i like strings',randomInt:60,isBoolean:true},
        {genProp:'this is a string',randomInt:70,isBoolean:true},
        {genProp:'this string is unique',randomInt:50,isBoolean:true},
        {genProp:'this is a string',randomInt:50,isBoolean:false},
        {genProp:'i like strings',randomInt:70,isBoolean:false}
    ]

Il accepte un paramètre supplémentaire appelé propertyName, suppose! :)

  $.extend({
        distinctObj:function(obj,propertyName) {
            var result = [];
            $.each(obj,function(i,v){
                var prop=eval("v."+propertyName);
                if ($.inArray(prop, result) == -1) result.Push(prop);
            });
            return result;
        }
    });

donc, si vous devez extraire une liste de valeurs uniques pour une propriété donnée, par exemple les valeurs utilisées pour la propriété randomInt, utilisez ceci:

$.distinctObj(genericObject,'genProp');

il retourne un tableau comme ceci:

["this is a string", "this is another string", "i like strings", "this string is unique"] 
5
Dariozzo

Paul Irish a une méthode " Duck Punching " (voir exemple 2) qui modifie la méthode $.unique() de jQuery pour renvoyer des éléments uniques de tout type:

(function($){
    var _old = $.unique;
    $.unique = function(arr){
        // do the default behavior only if we got an array of elements
        if (!!arr[0].nodeType){
            return _old.apply(this,arguments);
        } else {
            // reduce the array to contain no dupes via grep/inArray
            return $.grep(arr,function(v,k){
                return $.inArray(v,arr) === k;
            });
        }
    };
})(jQuery);
5
Mottie

Solution moderne simple en JavaScript si vous n'avez pas besoin de la prise en charge de IE (Array.from n'est pas pris en charge dans IE).

Vous pouvez utiliser la combinaison de Set et Array.from .

var arr = [1, 1, 11, 2, 4, 2, 5, 3, 1];
var set = new Set(arr);
arr = Array.from(set);

console.log(arr);

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.

La méthode Array.from() crée une nouvelle instance Array à partir d'un objet semblable à un tableau ou itératif.

1
Vadim Ovchinnikov

Vous pouvez utiliser un plugin jQuery appelé Array Utilities pour obtenir un tableau d'éléments uniques . Cela peut être fait comme ceci:

var distinctArray = $.distinct([1, 2, 2, 3])

distinctArray = [1,2,3]

1

Si quelqu'un utilise knockoutjs try:

ko.utils.arrayGetDistinctValues()

BTW a regardé tous les utilitaires ko.utils.array*.

1
Torbjörn Nomell

A partir de jquery 3.0, vous pouvez utiliser $.uniqueSort(ARRAY)

Exemple

array = ["1","2","1","2"]
$.uniqueSort(array)
=> ["1", "2"]
0
Joseph N.