Skip to main content
logic fix
Source Link
Pebbl
  • 161
  • 3
  • 11

For me, I'd always avoid methods that require lots of includes to things get working - and in my mind, the more code used.. the slower things will be (unless some form of caching is used). Which is why I would opt for a simple JavaScript solution. Your idea will work, but I think this one is faster:

Array.prototype.unique = function () {
  var a = this, b = [], c, i = a.length;
  again: while ( i-- ) {
    c = a[i];
    k = i; while( k-- ){ if (a[k] == c){ continue again; } }
    b.unshift( a[i] );
  }
  return b;
}

There are probably other improvements that can be made, for example it might be faster to find a way to use .push() rather than .unshift().

I haven't tested the above excessively, but it seems to work in all my tests so far. The reason why it gets a speed increase is because it reduces the area it is checking each time; it is also using subtle other speed increases like a decrementing while loop (means there are less conditional statements to check on each iteration), and creating shortcut vars that cut down access time.

As proof here is a jsPerf... albeit only tested on my set-up so far ;)

http://jsperf.com/compare-array-unique-versions

side note: -- the downside to my method is that it will only include the last found occurance of a duplicate (not the first as your's will). So if that ordering is important to you, then you'll have to refactor the code.

revision: -- after a few jsPerfs it seems clear that the while(i--) no longer holds a speed difference (at least not for FireFox 16 Mac OSX). Whilst on Chrome Mac OSX i--; seems slower than i++;

http://jsperf.com/compare-a-dec-while-against-a-for-loop

So taking in to account BillyBarry's comments the improved version should be:

Array.prototype.unique8 = function () {
  var a = this, b = [], c, i, l = a.length, j, k = 0;
  again: for ( i = 0; i < l; i++ ) {
    c = a[i];
    for ( j = 0; j < k; j++ ) { if (b[j] === c){ continue again; } }
    b[k++] = c;
  }
  return b;
}

Working from b, rather than a improves things quite a lot. Plus using k++; rather than .length for the internal loop makes quite a bit of difference for FireFox (Mac OSX) but has no affect on Chrome.

For me, I'd always avoid methods that require lots of includes to things get working - and in my mind, the more code used.. the slower things will be (unless some form of caching is used). Which is why I would opt for a simple JavaScript solution. Your idea will work, but I think this one is faster:

Array.prototype.unique = function () {
  var a = this, b = [], c, i = a.length;
  again: while ( i-- ) {
    c = a[i];
    k = i; while( k-- ){ if (a[k] == c){ continue again; } }
    b.unshift( a[i] );
  }
  return b;
}

There are probably other improvements that can be made, for example it might be faster to find a way to use .push() rather than .unshift().

I haven't tested the above excessively, but it seems to work in all my tests so far. The reason why it gets a speed increase is because it reduces the area it is checking each time; it is also using subtle other speed increases like a decrementing while loop (means there are less conditional statements to check on each iteration), and creating shortcut vars that cut down access time.

As proof here is a jsPerf... albeit only tested on my set-up so far ;)

http://jsperf.com/compare-array-unique-versions

side note: -- the downside to my method is that it will only include the last found occurance of a duplicate (not the first as your's will). So if that ordering is important to you, then you'll have to refactor the code.

For me, I'd always avoid methods that require lots of includes to things get working - and in my mind, the more code used.. the slower things will be (unless some form of caching is used). Which is why I would opt for a simple JavaScript solution. Your idea will work, but I think this one is faster:

Array.prototype.unique = function () {
  var a = this, b = [], c, i = a.length;
  again: while ( i-- ) {
    c = a[i];
    k = i; while( k-- ){ if (a[k] == c){ continue again; } }
    b.unshift( a[i] );
  }
  return b;
}

There are probably other improvements that can be made, for example it might be faster to find a way to use .push() rather than .unshift().

I haven't tested the above excessively, but it seems to work in all my tests so far. The reason why it gets a speed increase is because it reduces the area it is checking each time; it is also using subtle other speed increases like a decrementing while loop (means there are less conditional statements to check on each iteration), and creating shortcut vars that cut down access time.

As proof here is a jsPerf... albeit only tested on my set-up so far ;)

http://jsperf.com/compare-array-unique-versions

side note: -- the downside to my method is that it will only include the last found occurance of a duplicate (not the first as your's will). So if that ordering is important to you, then you'll have to refactor the code.

revision: -- after a few jsPerfs it seems clear that the while(i--) no longer holds a speed difference (at least not for FireFox 16 Mac OSX). Whilst on Chrome Mac OSX i--; seems slower than i++;

http://jsperf.com/compare-a-dec-while-against-a-for-loop

So taking in to account BillyBarry's comments the improved version should be:

Array.prototype.unique8 = function () {
  var a = this, b = [], c, i, l = a.length, j, k = 0;
  again: for ( i = 0; i < l; i++ ) {
    c = a[i];
    for ( j = 0; j < k; j++ ) { if (b[j] === c){ continue again; } }
    b[k++] = c;
  }
  return b;
}

Working from b, rather than a improves things quite a lot. Plus using k++; rather than .length for the internal loop makes quite a bit of difference for FireFox (Mac OSX) but has no affect on Chrome.

Source Link
Pebbl
  • 161
  • 3
  • 11

For me, I'd always avoid methods that require lots of includes to things get working - and in my mind, the more code used.. the slower things will be (unless some form of caching is used). Which is why I would opt for a simple JavaScript solution. Your idea will work, but I think this one is faster:

Array.prototype.unique = function () {
  var a = this, b = [], c, i = a.length;
  again: while ( i-- ) {
    c = a[i];
    k = i; while( k-- ){ if (a[k] == c){ continue again; } }
    b.unshift( a[i] );
  }
  return b;
}

There are probably other improvements that can be made, for example it might be faster to find a way to use .push() rather than .unshift().

I haven't tested the above excessively, but it seems to work in all my tests so far. The reason why it gets a speed increase is because it reduces the area it is checking each time; it is also using subtle other speed increases like a decrementing while loop (means there are less conditional statements to check on each iteration), and creating shortcut vars that cut down access time.

As proof here is a jsPerf... albeit only tested on my set-up so far ;)

http://jsperf.com/compare-array-unique-versions

side note: -- the downside to my method is that it will only include the last found occurance of a duplicate (not the first as your's will). So if that ordering is important to you, then you'll have to refactor the code.