Is there an indexOf in javascript to search an array with custom compare function

后端 未结 8 1728
执笔经年
执笔经年 2020-12-05 18:05

I need the index of the first value in the array, that matches a custom compare function.

The very nice underscorej has a \"find\" function that returns the

相关标签:
8条回答
  • 2020-12-05 18:16

    using underscore I came up with something copied from their find implementation using _.any:

    findIndex = function (obj, iterator, context) {
        var idx;
        _.any(obj, function (value, index, list) {
            if (iterator.call(context, value, index, list)) {
                idx = index;
                return true;
            }
        });
        return idx;
    };
    

    What do you think - do you have any better solutions?

    0 讨论(0)
  • 2020-12-05 18:19

    There's a standard function in ECMAScript 2015 for Array.prototype.findIndex(). Currently it's implemented in all major browsers apart from Internet Explorer.

    Here's a polyfill, courtesy of the Mozilla Developer Network:

    // https://tc39.github.io/ecma262/#sec-array.prototype.findIndex
    if (!Array.prototype.findIndex) {
      Object.defineProperty(Array.prototype, 'findIndex', {
        value: function(predicate) {
         // 1. Let O be ? ToObject(this value).
          if (this == null) {
            throw new TypeError('"this" is null or not defined');
          }
    
          var o = Object(this);
    
          // 2. Let len be ? ToLength(? Get(O, "length")).
          var len = o.length >>> 0;
    
          // 3. If IsCallable(predicate) is false, throw a TypeError exception.
          if (typeof predicate !== 'function') {
            throw new TypeError('predicate must be a function');
          }
    
          // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
          var thisArg = arguments[1];
    
          // 5. Let k be 0.
          var k = 0;
    
          // 6. Repeat, while k < len
          while (k < len) {
            // a. Let Pk be ! ToString(k).
            // b. Let kValue be ? Get(O, Pk).
            // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
            // d. If testResult is true, return k.
            var kValue = o[k];
            if (predicate.call(thisArg, kValue, k, o)) {
              return k;
            }
            // e. Increase k by 1.
            k++;
          }
    
          // 7. Return -1.
          return -1;
        },
        configurable: true,
        writable: true
      });
    }
    
    0 讨论(0)
  • 2020-12-05 18:21

    How about such find function ?

    (function () {
      if (!Array.prototype._find) {
        Array.prototype._find = function (value) {
          var i = -1, j = this.length;
          if (typeof(value)=="function") 
             for(; (++i < j) && !value(this[i]););
          else
             for(; (++i < j) && !(this[i] === value););
    
          return i!=j ? i : -1;
        }
      }
    }());
    
    0 讨论(0)
  • 2020-12-05 18:30

    As others have noted, easy enough to roll your own, which you can keep short and simple for your particular use case:

    // Find the index of the first element in array
    // meeting specified condition.
    //
    var findIndex = function(arr, cond) {
      var i, x;
      for (i in arr) {
        x = arr[i];
        if (cond(x)) return parseInt(i);
      }
    };
    
    var moreThanTwo = function(x) { return x > 2 }
    var i = findIndex([1, 2, 3, 4], moreThanTwo)
    

    Or if you're a CoffeeScripter:

    findIndex = (arr, cond) ->
      for i, x of arr
        return parseInt(i) if cond(x)
    
    0 讨论(0)
  • 2020-12-05 18:31

    You could do something like this:

    Array.prototype.myIndexOf = function(f)
    {
        for(var i=0; i<this.length; ++i)
        {
            if( f(this[i]) )
                return i;
        }
        return -1;
    };
    

    Regarding Christian's comment: if you override a standard JavaScript method with a custom one with a different the same signature and different functionality, bad thing will likely happen. This is especially true if you're pulling in 3rd party libraries which may depend on the original, say, Array.proto.indexOf. So yeah, you probably want to call it something else.

    0 讨论(0)
  • 2020-12-05 18:33

    Here comes the coffeescript version of nrabinowitz's code.

    # save a reference to the core implementation
    indexOfValue = _.indexOf
    
    # using .mixin allows both wrapped and unwrapped calls:
    # _(array).indexOf(...) and _.indexOf(array, ...)
    _.mixin ({
        # return the index of the first array element passing a test
        indexOf: (array, test) ->
            # delegate to standard indexOf if the test isn't a function
            if (!_.isFunction(test))
                return indexOfValue(array, test)
            # otherwise, look for the index
            for item, i in array
                return i if (test(item))
            # not found, return fail value
            return -1
    })
    
    0 讨论(0)
提交回复
热议问题