关于javascript:jQuery函数从数组中获取所有独特元素?

jQuery function to get all unique elements from an array?

jquery.unique允许您获取数组的唯一元素,但是文档说该函数主要用于内部使用,并且只在dom元素上操作。另一个so响应说unique()函数处理数字,但是这个用例不一定是未来的证据,因为它在文档中没有明确说明。

考虑到这一点,是否有一个"标准"jquery函数只访问数组中的唯一值——特别是像整数这样的基元?(很明显,我们可以用each()函数构造一个循环,但是我们对jquery还比较陌生,想知道是否有专门的jquery函数用于这个循环。)


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

1
2
3
4
5
6
7
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方法。

否则,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
    }
}


只需使用此代码作为简单jquery插件的基础。

1
2
3
4
5
6
7
8
9
$.extend({
    distinct : function(anArray) {
       var result = [];
       $.each(anArray, function(i,v){
           if ($.inArray(v, result) == -1) result.push(v);
       });
       return result;
    }
});

使用如下:

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


基于@Kennebec的答案,但通过在数组周围使用jquery包装器提供缺少的数组函数filterindexOf,修复了IE8及以下版本:

可能绝对不需要$.MakeArray()包装器,但如果省略此包装器和json.Stringify结果,则会得到奇怪的结果。

1
2
3
4
5
6
7
8
9
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]


我将使用underline.js,它提供了一个执行所需操作的uniq方法。


1
2
3
4
5
6
7
8
9
    // 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/


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

请注意,这只适用于原语(字符串、数字、空值、未定义、NaN)和一些序列化为相同内容的对象(函数、字符串、日期,可能是数组,具体取决于内容)。当散列都序列化到同一个对象时,其中的散列将发生冲突,例如:"[对象对象对象]"

1
2
3
4
5
6
7
8
9
10
11
12
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。我唯一不喜欢的是它破坏了数组的顺序。如果您感兴趣的话,这里是它的确切代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
};


1
2
3
4
5
6
7
8
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;
}

这是JS1568的解决方案,修改后可用于一般对象数组,如:

1
2
3
4
5
6
7
8
9
10
11
12
 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的参数,猜猜看!:)

1
2
3
4
5
6
7
8
9
10
  $.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;
        }
    });

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

1
$.distinctObj(genericObject,'genProp');

它返回这样的数组:

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


Paul Irish有一个"duck punching"方法(参见示例2),它修改jquery的$.unique()方法以返回任何类型的唯一元素:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(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);

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

您可以使用SetArray.from的组合。

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

console.log(arr);

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

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


如果有人正在使用knockoutjs,请尝试:

1
ko.utils.arrayGetDistinctValues()

顺便说一下,我们已经了解了所有的ko.utils.array*实用程序。


可以使用名为array utilities的jquery插件来获取唯一项的数组。可以这样做:

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

DistinctArray=[1,2,3]


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

例子

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