Use PHP functions in JavaScript

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;
}
external links: original PHP docs | raw js source

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.

Comments

Add Comment
Use:
[CODE]
your_stuff('here');
[/CODE]
for proper code formatting
By submitting code here you are allowing us to use it in php.js hence dual licensing it under the MIT and GPL licenses

Gravatar
Thériault
Jun 9th Permalink

q  @t: Associative arrays aren't native to JavaScript, but JavaScript objects share similarities to PHP associative arrays, so to try and support associative arrays, the functions on PHP.JS convert JavaScript arrays to JavaScript objects.

Gravatar
t
Jun 8th Permalink

q  Why does this function return an object where as the php version returns an array?

Thanks

Gravatar
Brett Zamir
Mar 19th Permalink

q  But to make clear, it wasn't the position that was the problem, but the lack of an argument...Dumb oversight on my part...

Gravatar
Brett Zamir
Mar 19th Permalink

q  @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...

Gravatar
harald
Mar 19th Permalink

q  hello,

may i ask:

lines 25 and 35

why are you testing for hasOwnProperty inside the loop and not outside?

Gravatar
Brett Zamir
Feb 4th Permalink

q  @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.

Gravatar
nitin gupta
Feb 2nd Permalink

q  Hi Kevin,

I do not see this function being dependent on asort, may be a little documentation error.

Regards,

Gravatar
Kevin van Zonneveld
14 Apr '09 Permalink

q  Great work guys, I'll deploy shortly

Gravatar
Brett Zamir
14 Apr '09 Permalink

q  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

Gravatar
Michael Grier
13 Apr '09 Permalink

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

Gravatar
Kevin van Zonneveld
9 Nov '08 Permalink

q  @ Nate: Thank you for noticing!

Gravatar
Nate
6 Nov '08 Permalink

q  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().

Gravatar
Kevin van Zonneveld
27 Aug '08 Permalink

q  @ Nosredna: That's an idea that calls for a function rewrite. Interested? ;)

Gravatar
Nosredna
5 Aug '08 Permalink

q  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.

Gravatar
Kevin van Zonneveld
25 Jul '08 Permalink

q  @ 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

Gravatar
sankai
25 Jul '08 Permalink

q  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()

Gravatar
sankai
24 Jul '08 Permalink

q  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()

Gravatar
sankai
24 Jul '08 Permalink

q  Running:
[CODE="Javascript"]
array_unique(['Kevin','Kevin','van','Kevin']);
[/CODE]
Return:
[CODE="Javascript"]
['Kevin','van','Kevin']
[/CODE]
It's the same problem as @goshki ?

Gravatar
Kevin van Zonneveld
16 Jun '08 Permalink

q  @ 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!

Gravatar
goshki
13 Jun '08 Permalink

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

Gravatar
Kevin van Zonneveld
2 May '08 Permalink

q  @ duncan: You were not being stupid, we were. Thank you for noticing! The fixed version will be visible shortly.

Gravatar
duncan
30 Apr '08 Permalink

q  maybe i'm being stupid, but PHP array_unique returns an array, not a boolean.
"Takes an input array and returns a new array without duplicate values."


Contribute a New function