jQuery函数从数组中获取所有唯一元素?


71

jQuery.unique允许您获取数组的唯一元素,但是文档说该函数主要供内部使用,并且仅对DOM元素起作用。另一个SO响应说该unique()函数可以在数字上使用,但是此用例不一定是将来的证明,因为在文档中未明确说明。

鉴于此,是否存在“标准” jQuery函数,用于仅访问数组中的唯一值(特别是整数之类的基元)?(显然,我们可以使用函数构造一个循环each(),但是我们是jQuery的新手,并且想知道是否为此使用了专用的jQuery函数。)


2
@Future_Readers-在检查Rubyrider的答案时,请注意,使用它可能会看到意外的结果-这不是安全或可靠的解决方案。
Yuck

Answers:


125

您可以array.filter用来返回每个不同值的第一项-

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

如果主要支持IE8及以下版本,请不要使用不受支持的filter方法。

除此以外,

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

4
警告:上面的代码在IE8及以下版本中会崩溃,它们不支持Array.filterArray.indexOf。请参阅我对此答案的修订,以获取在受jquery支持的浏览器中不会中断的代码。
丹尼斯

在IE9中,开始支持更多信息,请访问developer.mozilla.org/en-US/docs/JavaScript/Reference/...
Organiccat

1
或使用许多EcmaScript 5垫片之一,例如Kriskowal
撰写的-Superjos

1
@cwolves的答案应该是被接受的。这个答案以及几乎所有其他答案都在O(n ^ 2)时间中运行,如果在大型数组上尝试,它将非常非常慢。
Alex D

简单的答案,太棒了。
bntzio

48

只需将此代码用作简单JQuery插件的基础即可。

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

如此使用:

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

13

基于@kennebec的答案,但针对IE8及以下版本,已通过在数组周围使用jQuery包装器提供缺少的Array函数filter和进行了修复indexOf

$ .makeArray()包装器可能不是绝对需要的,但是如果省略此包装器,而获得JSON.stringify结果,则会得到奇怪的结果。

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]

1
似乎不再起作用,将过滤器更改为:return i == $ .inArray(itm,a);
Shadaez 2015年


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

对于dom元素,我想这里不需要示例,因为您已经知道了!

这是实时示例的jsfiddle链接:http : //jsfiddle.net/3BtMc/4/


7
但是文档说$ .unique()适用于DOM元素!“对DOM元素数组进行适当排序,并删除重复项。请注意,这仅适用于DOM元素数组,不适用于字符串或数字。” - api.jquery.com/jquery.unique

6

遍历数组,并在遇到它们时将其推入哈希中。交叉引用每个新元素的哈希值。

请注意,这仅适用于原语(字符串,数字,null,未定义,NaN)和一些序列化为同一对象的对象(函数,字符串,日期,以及可能取决于内容的数组)。由于它们都序列化为同一事物,因此其中的哈希将发生冲突,例如“ [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;
}

也没有理由不能使用jQuery.unique。我唯一不喜欢的是它破坏了数组的顺序。如果您有兴趣,这里是确切的代码:

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

5

Paul Irish有一个“ Duck Punching ”方法(请参见示例2),该$.unique()方法修改了jQuery的方法以返回任何类型的唯一元素:

(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

这是js1568的解决方案,经过修改可在通用对象数组上工作,例如:

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

猜猜它还接受一个称为propertyName的参数!:)

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

因此,如果您需要提取给定属性的唯一值列表,例如,用于randomInt属性的值,请使用以下命令:

$.distinctObj(genericObject,'genProp');

它返回这样的数组:

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

我真的很想知道我写了什么应该得到-1。
Dariozzo 2014年

1
我没有投票(我刚刚看到了这个答案),但是我建议您更改eval("v."+propertyName)v[propertyName]。每次调用时,eval您都会启动另一个编译器。对于循环,这是非常昂贵的。
Shaz 2014年

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

3

如果您不需要IE支持(Array.from在IE中不支持),则使用普通的JavaScript现代解决方案。

您可以使用Set和的组合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);

Set对象允许您存储任何类型的唯一值,无论是原始值或对象引用。

Array.from()方法从类似数组或可迭代的对象中创建一个新的Array实例。

Array.from()可以用传播算子代替。

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

console.log(uniqueArr);


1
var arr = [1,1,11,2,4,4,2,5,3,1]; [... new Set(arr)];
Ashish Singh Rawat

@AshishSinghRawat谢谢,添加了具有传播运算符语法的选项。
Vadim Ovchinnikov



0

从jquery 3.0开始,您可以使用 $.uniqueSort(ARRAY)

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

实际上,uniqueSort它与uniquejquery 2中的相同。它旨在对对象而不是字符串进行排序。
迈克(Mike)

-1

如果您需要支持IE 8或更早版本,则可以使用jQuery完成。

var a = [1,2,2,3,4,3,5];
var unique = $.grep(a, function (item, index) {
   return index === $.inArray(item, a);
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.