jQuery function to get all unique elements from an

2020-01-23 07:30发布

问题:

jQuery.unique lets you get unique elements of an array, but the docs say the function is mostly for internal use and only operates on DOM elements. Another SO response said the unique() function worked on numbers, but that this use case is not necessarily future proof because it's not explicitly stated in the docs.

Given this, is there a "standard" jQuery function for accessing only the unique values — specifically, primitives like integers — in an array? (Obviously, we can construct a loop with the each() function, but we are new to jQuery and would like to know if there is a dedicated jQuery function for this.)

回答1:

You can use array.filter to return the first item of each distinct value-

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

If supporting IE8 and below is primary, don't use the unsupported filter method.

Otherwise,

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


回答2:

Just use this code as the basis of a simple JQuery plugin.

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

Use as so:

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


回答3:

Based on @kennebec's answer, but fixed for IE8 and below by using jQuery wrappers around the array to provide missing Array functions filter and indexOf:

$.makeArray() wrapper might not be absolutely needed, but you'll get odd results if you omit this wrapper and JSON.stringify the result otherwise.

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]


回答4:

I would use underscore.js, which provides a uniq method that does what you want.



回答5:

    // 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"]

And for dom elements there is no example is needed here I guess because you already know that!

Here is the jsfiddle link of live example: http://jsfiddle.net/3BtMc/4/



回答6:

Walk the array and push items into a hash as you come across them. Cross-reference the hash for each new element.

Note that this will ONLY work properly for primitives (strings, numbers, null, undefined, NaN) and a few objects that serialize to the same thing (functions, strings, dates, possibly arrays depending on content). Hashes in this will collide as they all serialize to the same thing, e.g. "[object Object]"

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

There's also no reason you can't use jQuery.unique. The only thing I don't like about it is that it destroys the ordering of your array. Here's the exact code for it if you're interested:

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


回答7:

Paul Irish has a "Duck Punching" method (see example 2) that modifies jQuery's $.unique() method to return unique elements of any 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);


回答8:

this is js1568's solution, modified to work on a generic array of objects, like:

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

It accepts one more parameter called propertyName, guess! :)

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

so, if you need to extract a list of unique values for a given property, for example the values used for randomInt property, use this:

$.distinctObj(genericObject,'genProp');

it returns an array like this:

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


回答9:

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


回答10:

Plain JavaScript modern solution if you don't need IE support (Array.from is not supported in IE).

You can use combination of Set and Array.from.

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

console.log(uniqueArr);

The Set object lets you store unique values of any type, whether primitive values or object references.

The Array.from() method creates a new Array instance from an array-like or iterable object.

Also Array.from() can be replaced with spread operator.

const arr = [1, 1, 11, 2, 4, 2, 5, 3, 1];
const set = new Set(arr);
const uniqueArr = [...set];

console.log(uniqueArr);



回答11:

You can use a jQuery plugin called Array Utilities to get an array of unique items. It can be done like this:

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

distinctArray = [1,2,3]



回答12:

If anyone is using knockoutjs try:

ko.utils.arrayGetDistinctValues()

BTW have look at all ko.utils.array* utilities.



回答13:

As of jquery 3.0 you can use $.uniqueSort(ARRAY)

Example

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


回答14:

If you need to support IE 8 or earlier, you can use jQuery to accomplish this.

var a = [1,2,2,3,4,3,5];
var unique = $.grep(a, function (item, index) {
   return index === $.inArray(item, a);
});