如何从 JavaScript 中包含重复数据的数组中获得唯一值的数组?

给定一个 ['0','1','1','2','3','3','3']数组,结果应该是 ['0','1','2','3']

158623 次浏览
function array_unique(nav_array) {
nav_array = nav_array.sort(function (a, b) { return a*1 - b*1; });
var ret = [nav_array[0]];
// Start loop at 1 as element 0 can never be a duplicate
for (var i = 1; i < nav_array.length; i++) {
if (nav_array[i-1] !== nav_array[i]) {
ret.push(nav_array[i]);
}
}
return ret;
}
function array_unique(arr) {
var result = [];
for (var i = 0; i < arr.length; i++) {
if (result.indexOf(arr[i]) == -1) {
result.push(arr[i]);
}
}
return result;
}

Not a built in function. If the product list does not contain the item, add it to unique list and return unique list.

If you want to maintain order:

arr = arr.reverse().filter(function (e, i, arr) {
return arr.indexOf(e, i+1) === -1;
}).reverse();

Since there's no built-in reverse indexof, I reverse the array, filter out duplicates, then re-reverse it.

The filter function looks for any occurence of the element after the current index (before in the original array). If one is found, it throws out this element.

Edit:

Alternatively, you could use lastindexOf (if you don't care about order):

arr = arr.filter(function (e, i, arr) {
return arr.lastIndexOf(e) === i;
});

This will keep unique elements, but only the last occurrence. This means that ['0', '1', '0'] becomes ['1', '0'], not ['0', '1'].

Here is an Array Prototype function:

Array.prototype.unique = function() {
var unique = [];
for (var i = 0; i < this.length; i++) {
if (unique.indexOf(this[i]) == -1) {
unique.push(this[i]);
}
}
return unique;
};

This will work. Try it.

function getUnique(a) {
var b = [a[0]], i, j, tmp;
for (i = 1; i < a.length; i++) {
tmp = 1;
for (j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
tmp = 0;
break;
}
}
if (tmp) {
b.push(a[i]);
}
}
return b;
}

There you go! You are welcome!

Array.prototype.unique = function()
{
var tmp = {}, out = [];
for(var i = 0, n = this.length; i < n; ++i)
{
if(!tmp[this[i]]) { tmp[this[i]] = true; out.push(this[i]); }
}
return out;
}


var a = [1,2,2,7,4,1,'a',0,6,9,'a'];
var b = a.unique();
alert(a);
alert(b);

No redundant "return" array, no ECMA5 (I'm pretty sure!) and simple to read.

function removeDuplicates(target_array) {
target_array.sort();
var i = 0;


while(i < target_array.length) {
if(target_array[i] === target_array[i+1]) {
target_array.splice(i+1,1);
}
else {
i += 1;
}
}
return target_array;
}

Edited

ES6 solution:

[...new Set(a)];

Alternative:

Array.from(new Set(a));

Old response. O(n^2) (do not use it with large arrays!)

var arrayUnique = function(a) {
return a.reduce(function(p, c) {
if (p.indexOf(c) < 0) p.push(c);
return p;
}, []);
};

I like to use this. There is nothing wrong with using the for loop, I just like using the build-in functions. You could even pass in a boolean argument for typecast or non typecast matching, which in that case you would use a for loop (the filter() method/function does typecast matching (===))

Array.prototype.unique =
function()
{
return this.filter(
function(val, i, arr)
{
return (i <= arr.indexOf(val));
}
);
}
    //
Array.prototype.unique =
( function ( _where ) {
return function () {
for (
var
i1 = 0,
dups;
i1 < this.length;
i1++
) {
if ( ( dups = _where( this, this[i1] ) ).length > 1 ) {
for (
var
i2 = dups.length;
--i2;
this.splice( dups[i2], 1 )
);
}
}
return this;
}
} )(
function ( arr, elem ) {
var locs  = [];
var tmpi  = arr.indexOf( elem, 0 );
while (
( tmpi ^ -1 )
&& (
locs.push( tmpi ),
tmpi = arr.indexOf( elem, tmpi + 1 ), 1
)
);
return locs;
}
);
//
Array.prototype.unique =function(){
var uniqObj={};
for(var i=0;i< this.length;i++){
uniqObj[this[i]]=this[i];
}
return uniqObj;
}

With underscorejs

_.uniq([1, 2, 1, 3, 1, 4]); //=> [1, 2, 3, 4]

You can find all kinds of array unique implementations here:

http://jsperf.com/distinct-hash-vs-comparison/12

http://jsperf.com/array-unique-functional

I prefer functional styles such as:

var arr = ['lol', 1, 'fdgdfg', 'lol', 'dfgfg', 'car', 1, 'car', 'a', 'blah', 'b', 'c', 'd', '0', '1', '1', '2', '3', '3', '3', 'crazy', 'moot', 'car', 'lol', 1, 'fdgdfg', 'lol', 'dfgfg', 'car', 1, 'car', 'a', 'blah', 'b', 'c', 'd', '0', '1', '1', '2', '3', '3', '3', 'crazy', 'moot', 'car', 'lol', 1, 'fdgdfg'];


var newarr = arr.reduce(function (prev, cur) {
//console.log(prev, cur);
if (prev.indexOf(cur) < 0) prev.push(cur);
return prev;
}, []);


var secarr = arr.filter(function(element, index, array){
//console.log(element, array.indexOf(element), index);
return array.indexOf(element) >= index;
});


//reverses the order
var thirdarr = arr.filter(function (e, i, arr) {
//console.log(e, arr.lastIndexOf(e), i);
return arr.lastIndexOf(e) === i;
});


console.log(newarr);
console.log(secarr);
console.log(thirdarr);

Those of you who work with google closure library, have at their disposal goog.array.removeDuplicates, which is the same as unique. It changes the array itself, though.

It's 2014 now guys, and time complexity still matters!

array.filter(function() {
var seen = {};
return function(element, index, array) {
return !(element in seen) && (seen[element] = 1);
};
}());

http://jsperf.com/array-filter-unique/13

Here is the way you can do remove duplicate values from the Array.

function ArrNoDupe(dupArray) {
var temp = {};
for (var i = 0; i < dupArray.length; i++) {
temp[dupArray[i]] = true;
var uniqueArray = [];
for (var k in temp)
uniqueArray.push(k);
return uniqueArray;
}
}

Another approach is to use an object for initial storage of the array information. Then convert back. For example:

var arr = ['0','1','1','2','3','3','3'];
var obj = {};


for(var i in arr)
obj[i] = true;


arr = [];
for(var i in obj)
arr.push(i);

Variable "arr" now contains ["0", "1", "2", "3", "4", "5", "6"]