Uniquing a collection (v3)

Revision 3 of this benchmark created by Curtis Cummings on


Description

Just trying to find a performant way of creating a "uniqued" array that leave copies in, only removed actual duplicate entries (obj === obj).

Set does not work properly in IE/Safari so they will use the first algorithm.

Preparation HTML

<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js"></script>

Setup

window.N = 999;
    var initialArray = [];
    var seeds = [{ one: 1 }, { two: 2 }, { three: 3 }];
    var setSupport = (function(){
      var s = new Set([1,2]);
      return s.size == 2;
    })();
    
    for(var i = 0, len = N; i < len; i++) {
      var isCopy = i % 2;
      var seed = seeds[(i % 3)];
      if(isCopy) {
        initialArray.push(_.clone(seed));
      } else {
        initialArray.push(seed);
      }
    }
    
    var result;
    
    function uniq1(ar) {
        var copy = ar.slice(0, ar.length);
        var result = [];
        for (var i = 0, len = copy.length, item; i < len; i++) {
            item = copy.shift();
            if (copy.indexOf(item) === -1) {
                result.push(item);
            }
        }
        return result;
    }
    
    function uniq2(ar) {
        var r = [];
        var s = new Set(ar);
        s.forEach(function(val) {
            r.push(val);
        });
        return r;
    }
    
    if(!setSupport){
      uniq2 = uniq1;
    }
    
    function uniq3(arr) {
        var uniqArr = [],
            expando = "__expando234234i028290348",
            instance;
    
        // check for expando and add it
        for (var i = 0, len = arr.length; i < len; i++) {
            instance = arr[i];
            if (!instance[expando]) { // is unique
                uniqArr.push(instance);
            }
            instance[expando] = true;
        }
        // clean up expandos
        for (var j = 0; j < len; j++) {
            delete arr[j][expando];
        }
        return uniqArr;
    }
    
    function uniq4(arr){
      var items = [];
      var unique = new WeakMap();
      arr.forEach(function(item){
        if(!unique.has(item)) {
          unique.set(item, true);
          items.push(item);
        }
      });
      return items;
    }
    
    function uniq5(arr){
      var items = [];
      var unique = new Map();
      arr.forEach(function(item){
        if(!unique.has(item)) {
          unique.set(item, true);
          items.push(item);
        }
      });
      return items;
    }
    
    function uniq6(a) {
      var add;
      var arr = [];
      for(var i = 0, l = a.length; i < l; i++) {
        add = 1;
        for(var o = 0, p = arr.length; o < p; o++) {
          if (a[i] === arr[o]) {
            add = 0;
          }
        }
        if (add) {
          arr.push(a[i]);
        }
      }
      return arr;
    }

Teardown


    console.assert(result.length === Math.floor(window.N/2) + 3);
  

Test runner

Ready to run.

Testing in
TestOps/sec
Unique using indexOf and O(N^2)
result = uniq1(initialArray)
ready
Unique using Set
result = uniq2(initialArray)
ready
Unique using expando prop
result = uniq3(initialArray)
ready
Unique using WeakMap
result = uniq4(initialArray)
ready
Unique using Map
result = uniq5(initialArray)
ready
Ben
result = uniq6(initialArray)
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 3: published by Curtis Cummings on