JavaScript array_unique
Removes duplicate values from array
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 | function array_unique (inputArr) { // Removes duplicate values from array // // version: 1008.1718 // discuss at: http://phpjs.org/functions/array_unique // + original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com) // + input by: duncan // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Nate // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Michael Grier // + bugfixed by: Brett Zamir (http://brett-zamir.me) // % note 1: The second argument, sort_flags is not implemented; // % note 1: also should be sorted (asort?) first according to docs // * example 1: array_unique(['Kevin','Kevin','van','Zonneveld','Kevin']); // * returns 1: {0: 'Kevin', 2: 'van', 3: 'Zonneveld'} // * example 2: array_unique({'a': 'green', 0: 'red', 'b': 'green', 1: 'blue', 2: 'red'}); // * returns 2: {a: 'green', 0: 'red', 1: 'blue'} var key = '', tmp_arr2 = {}, val = ''; var __array_search = function (needle, haystack) { var fkey = ''; for (fkey in haystack) { if (haystack.hasOwnProperty(fkey)) { if ((haystack[fkey] + '') === (needle + '')) { return fkey; } } } return false; }; for (key in inputArr) { if (inputArr.hasOwnProperty(key)) { val = inputArr[key]; if (false === __array_search(val, tmp_arr2)) { tmp_arr2[key] = val; } } } return tmp_arr2; } |
Examples
» Example 1
Running
1 | array_unique(['Kevin','Kevin','van','Zonneveld','Kevin']); |
Should return
1 | {0: 'Kevin', 2: 'van', 3: 'Zonneveld'} |
» Example 2
Running
1 | array_unique({'a': 'green', 0: 'red', 'b': 'green', 1: 'blue', 2: 'red'}); |
Should return
1 | {a: 'green', 0: 'red', 1: 'blue'} |
Dependencies
No dependencies, you can use this function standalone.
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have array_unique goodness in JavaScript.
But to make clear, it wasn't the position that was the problem, but the lack of an argument...Dumb oversight on my part...
@harald: Sorry, fixed in git: http://github.com/kvz/phpjs/raw/master/functions/array/array_unique.js . See https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Object/hasOwnProperty for an explanation of the method. It is used to make sure we are only iterating over the immediate properties of the object, and not any that may have been added on an inherited class or on the Object/Array prototype itself...
hello,
may i ask:
lines 25 and 35
why are you testing for hasOwnProperty inside the loop and not outside?
@nitin gupta: Thanks--I've fixed it in Git. I think it is a relic of the fact that we noticed that we may still _need_ to sort according to the docs, but I'm a bit busy to look at fixing this now myself.
Hi Kevin,
I do not see this function being dependent on asort, may be a little documentation error.
Regards,
Ok, I made the strict fix, Michael, in SVN, thank you!
However, I'm not sure about the array-to-objects issue. Although we can get an array to return, due to the nature of JS, it will only contain the numerically indexed items within the array (and the length will be the total of those only). The other items would be added as properties of that array's object, and not be counted with length, though they are iteratable. Kevin has chosen to implement PHP arrays as regular (non-array) objects, so that we can support associative arrays. Granted we could theoretically return arrays with object properties, but that might be more confusing, and perhaps is the reason he chose not to do that.
One solution, might be to detect whether the input array was indeed a genuine array (which could only be numerically indexed), and if so, build a bona fide array as output too, but the problem with that is that the PHP behavior is to preserve keys, and we cannot preserve keys unless we build an object (or delete/cause to be undefined, those items which are no longer in use, but that still keeps the array length)--the one rare exception where we could safely return a regular array would be if all of the unique items were at the front of the array... So, not any good answers, I suspect, though I imagine you personally should be able to adapt the output of our function to the form you need for Greasemonkey... Best wishes, Brett
I found out if you're using this in GreaseMonkey, objects won't return. I changed the tmp_arr declarations to array, and it started working for me.
Also, regarding the strict var, PHP always does a strict comparison after casting the arguments to strings. So you could do the following:
if ((haystack[fkey] + "") === (needle + "")) {
return fkey;
}
It looks like someone forgot to declare "val" with var.
I think the first line of code should read:
var key = '', tmp_arr1 = {}, tmp_arr2 = {}, val;
Otherwise, "val" is a global variable, I believe.
Is there any benefit to using var in a for loop? Would it be better to also declare "fkey" with "strict"?
Also, I don't know if this is important, but there is no space between "for" and "if" and the opening parentheses in __array_search().
Stray thought. The nested loops make me wonder how slow this is for large arrays.
Perhaps you could clone the array, sort the clone, then walk the two arrays deleting the dupes as you go. Sort is probably O(n log n) and maybe it's especially fast when no user sort evaluation routine is passed in.
@ sankai: Thank you so much! But this array_unique does not support associative arrays (javascript objects). So unlike PHP's implementation, arrays that have non-numeric keys do not work.
Sad to say that my implementation didn't support it either, but I'm looking to replace array_unique with one that does support:
[CODE="Javascript"]
{firstname: 'Kevin', surname: 'van Zonneveld'}
[/CODE]
.. style arrays
the code I posted yesterday had big bug!I fixed it as the following:
[CODE="Javascript"]
function array_unique(array,numeric){
// http://blog.doublekai.org/
// + original by: sankai (http://blog.doublekai.org/)
// * example 1: array_unique([1,2,3,'1','2','3',1,2,3],true);
// * returns 1: [1,2,3]
// * example 2: array_unique([1,2,3,'1','2','3',1,2,3]);
// * returns 2: [1,2,3,'1','2','3']
// * example 3: array_unique([1,'a','a','1','3',3,'b','c','b',1]);
// * returns 3: [1,'a','1','3',3,'b','c']
// * example 3: array_unique([1,'a','a','1','3',3,'b','c','b',1],true);
// * returns 3: [1,'a',3,'b','c']
// * NOTE :require function in_array()
var tem_arr = new Array();
for(i=0;i<array.length;i++){
if(numeric === true && typeof(array[i]) == 'string' && !isNaN(array[i])){
array[i]=parseInt(array[i],10);
}
if(!in_array(array[i],tem_arr)){
tem_arr[i]=array[i];
}
}
return tem_arr.join(' ').replace(/\s{2,}/g,' ').split(' ');
}
[/CODE]
The version need require function in_array
[CODE="Javascript"]
function array_unique(array,numeric){
// http://blog.doublekai.org/
// + original by: sankai (http://blog.doublekai.org/)
// * example 1: array_unique([1,2,3,'1','2','3',1,2,3],true);
// * returns 1: [1,2,3]
// * example 2: array_unique([1,2,3,'1','2','3',1,2,3]);
// * returns 2: [1,2,3,'1','2','3']
// * example 3: array_unique([1,'a','a','1','3',3,'b','c','b',1]);
// * returns 3: [1,'a','1','3',3,'b','c']
// * example 3: array_unique([1,'a','a','1','3',3,'b','c','b',1],true);
// * returns 3: [1,'a',3,'b','c']
// * DON'T NEED require function in_array()
var tem_arr = new Array();
for(i=0;i<array.length;i++){
if(numeric === true && typeof(array[i]) == 'string' && !isNaN(array[i])){
array[i]=parseInt(array[i],10);
}
if(tem_arr.length == 0){
tem_arr[i] = array[i];
} else {
var exist = false;
for(var j=0; j<tem_arr.length; j++){
if(tem_arr[j] === array[i]){
exist = true;
}
}
if(!exist){
if(array[i] != null){
tem_arr[i] = array[i];
}
}
}
}
return tem_arr.join(' ').replace(/\s{2,}/g,' ').split(' ');
}
[/CODE]
The version don't need require funciton in_array()
Hi,I try to write a code for array_unique() as the following:
[CODE="Javascript"]
function array_unique(array){
var tem_arr = new Array();
for(i=0;i<array.length;i++){
if(!in_array(array[i],tem_arr)){
tem_arr[i]=array[i];
}
}
return tem_arr.join(',').split(',');
}
[/CODE]
NOTE:It's require function in_array()
Running:
[CODE="Javascript"]
array_unique(['Kevin','Kevin','van','Kevin']);
[/CODE]
Return:
[CODE="Javascript"]
['Kevin','van','Kevin']
[/CODE]
It's the same problem as @goshki ?
@ goshki: You're right, it seems that our current version doesn't support associative arrays (javascript objects). Since PHP doesn't distinct those, we need to work on a version that does support objects. It's on my todo list. Thank your for noticing!
Well, there seems to be some kind of a problem with this function. Running:
[CODE="Javascript"]
array_unique(['a','b','c','a','b','c','a','b','c']);
[/CODE]
returns:
[CODE="Javascript"]
['a','a','b','c']
[/CODE]


Thériault
Jun 9th