Array Filter perf. (v10)

Revision 10 of this benchmark created on


Preparation HTML

<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script src="//underscorejs.org/underscore-min.js"></script>
<script src="//knockoutjs.com/downloads/knockout-3.2.0.js"></script>

Setup

var list = [];
    for (var l = 0; l < 100; l++) {
        list[l] = {
            id: l,
            code: l.toString(),
            text: "Item #" + l
        };
    }
    
    var onLoop = function onLoop(item) {
        return item.id > 20 && item.id <= 60;
    };
    
    function filterFilter() {
      return function(array, expression, comparator) {
        if (!isArray(array)) return array;
    
        var comparatorType = typeof(comparator),
            predicates = [];
    
        predicates.check = function(value, index) {
          for (var j = 0; j < predicates.length; j++) {
            if(!predicates[j](value, index)) {
              return false;
            }
          }
          return true;
        };
    
        if (comparatorType !== 'function') {
          if (comparatorType === 'boolean' && comparator) {
            comparator = function(obj, text) {
              return angular.equals(obj, text);
            };
          } else {
            comparator = function(obj, text) {
              if (obj && text && typeof obj === 'object' && typeof text === 'object') {
                for (var objKey in obj) {
                  if (objKey.charAt(0) !== '$' && hasOwnProperty.call(obj, objKey) &&
                      comparator(obj[objKey], text[objKey])) {
                    return true;
                  }
                }
                return false;
              }
              text = (''+text).toLowerCase();
              return (''+obj).toLowerCase().indexOf(text) > -1;
            };
          }
        }
    
        var search = function(obj, text){
          if (typeof text === 'string' && text.charAt(0) === '!') {
            return !search(obj, text.substr(1));
          }
          switch (typeof obj) {
            case 'boolean':
            case 'number':
            case 'string':
              return comparator(obj, text);
            case 'object':
              switch (typeof text) {
                case 'object':
                  return comparator(obj, text);
                default:
                  for ( var objKey in obj) {
                    if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
                      return true;
                    }
                  }
                  break;
              }
              return false;
            case 'array':
              for ( var i = 0; i < obj.length; i++) {
                if (search(obj[i], text)) {
                  return true;
                }
              }
              return false;
            default:
              return false;
          }
        };
        switch (typeof expression) {
          case 'boolean':
          case 'number':
          case 'string':
            // Set up expression object and fall through
            expression = {$:expression};
            // jshint -W086
          case 'object':
            // jshint +W086
            for (var key in expression) {
              (function(path) {
                if (typeof expression[path] === 'undefined') return;
                predicates.push(function(value) {
                  return search(path == '$' ? value : (value && value[path]), expression[path]);
                });
              })(key);
            }
            break;
          case 'function':
            predicates.push(expression);
            break;
          default:
            return array;
        }
        var filtered = [];
        for ( var j = 0; j < array.length; j++) {
          var value = array[j];
          if (predicates.check(value, j)) {
            filtered.push(value);
          }
        }
        return filtered;
      };
    }
    
    var isArray = angular.isArray;
    var ngFilter = filterFilter();

Test runner

Ready to run.

Testing in
TestOps/sec
KO arrayFilter
ko.utils.arrayFilter(list, onLoop);
ready
_ filter
_.filter(list, onLoop);
ready
jQuery grep
jQuery.grep(list, onLoop);
ready
Native filter
list.filter(onLoop);
ready

Revisions

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