322

我想知道是否有一种已知的、内置/优雅的方法来查找与给定条件匹配的 JS 数组的第一个元素。AC# 等效项是List.Find

到目前为止,我一直在使用这样的两个功能组合:

// Returns the first element of an array that satisfies given predicate
Array.prototype.findFirst = function (predicateCallback) {
    if (typeof predicateCallback !== 'function') {
        return undefined;
    }

    for (var i = 0; i < arr.length; i++) {
        if (i in this && predicateCallback(this[i])) return this[i];
    }

    return undefined;
};

// Check if element is not undefined && not null
isNotNullNorUndefined = function (o) {
    return (typeof (o) !== 'undefined' && o !== null);
};

然后我可以使用:

var result = someArray.findFirst(isNotNullNorUndefined);

但是由于ECMAScript 中有这么多函数式数组方法,也许已经有这样的东西了?我想很多人必须一直实现这样的东西......

4

13 回答 13

372

由于 ES6 有数组的原生find方法;一旦找到第一个匹配项并返回值,这将停止枚举数组。

const result = someArray.find(isNotNullNorUndefined);

老答案:

我必须发布一个答案来阻止这些filter建议:-)

由于 ECMAScript 中有这么多函数式数组方法,也许已经有这样的东西了?

您可以使用someArray 方法迭代数组,直到满足条件(然后停止)。不幸的是,它只会返回条件是否满足一次,而不是由哪个元素(或在哪个索引处)满足。所以我们必须稍微修改一下:

function find(arr, test, ctx) {
    var result = null;
    arr.some(function(el, i) {
        return test.call(ctx, el, i, arr) ? ((result = el), true) : false;
    });
    return result;
}
var result = find(someArray, isNotNullNorUndefined);
于 2013-08-29T20:20:27.887 回答
126

从 ECMAScript 6 开始,您可以使用Array.prototype.find它。这是在 Firefox (25.0)、Chrome (45.0)、Edge (12) 和 Safari (7.1) 中实现和运行的,但在 Internet Explorer 或其他一些旧的或不常见的平台中却没有。

例如,x下面是106

const x = [100,101,102,103,104,105,106,107,108,109].find(function (el) {
    return el > 105;
});
console.log(x);

如果您想立即使用它但需要支持 IE 或其他不支持的浏览器,您可以使用 shim。我推荐es6-shim。如果出于某种原因您不想将整个 es6-shim 放入您的项目中,MDN 还提供了一个 shim 。为了获得最大的兼容性,您需要 es6-shim,因为与 MDN 版本不同,它会检测错误的本机实现find并覆盖它们(请参阅以“Workaround bugs in Array#find and Array#findIndex”开头的注释以及紧随其后的行) .

于 2014-02-03T23:33:11.183 回答
74

那么使用过滤器并从结果数组中获取第一个索引呢?

var result = someArray.filter(isNotNullNorUndefined)[0];
于 2013-08-28T15:54:37.737 回答
40

概括:

  • 为了找到数组中与布尔条件匹配的第一个元素,我们可以使用ES6 find()
  • find()位于,Array.prototype因此它可以在每个阵列上使用。
  • find()接受boolean测试条件的回调。该函数返回(不是索引!)

例子:

const array = [4, 33, 8, 56, 23];

const found = array.find(element => {
  return element > 50;
});

console.log(found);   //  56

于 2018-08-19T11:46:10.543 回答
15

现在应该很清楚,JavaScript 本身并没有提供这样的解决方案。这是最接近的两个衍生物,最有用的第一个:

  1. Array.prototype.some(fn)在满足条件时提供所需的停止行为,但仅返回元素是否存在;应用一些技巧并不难,例如Bergi's answer提供的解决方案。

  2. Array.prototype.filter(fn)[0]制作一个很棒的单线,但效率最低,因为你扔掉N - 1元素只是为了得到你需要的东西。

JavaScript 中的传统搜索方法的特点是返回找到的元素的索引,而不是返回元素本身或 -1。这避免了必须从所有可能类型的域中选择返回值;索引只能是数字,负值无效。

上面的两种解决方案都不支持偏移搜索,所以我决定写这个:

(function(ns) {
  ns.search = function(array, callback, offset) {
    var size = array.length;

    offset = offset || 0;
    if (offset >= size || offset <= -size) {
      return -1;
    } else if (offset < 0) {
      offset = size - offset;
    }

    while (offset < size) {
      if (callback(array[offset], offset, array)) {
        return offset;
      }
      ++offset;
    }
    return -1;
  };
}(this));

search([1, 2, NaN, 4], Number.isNaN); // 2
search([1, 2, 3, 4], Number.isNaN); // -1
search([1, NaN, 3, NaN], Number.isNaN, 2); // 3
于 2013-09-17T04:57:48.353 回答
9

如果你正在使用underscore.js,你可以使用它的findindexOf函数来得到你想要的:

var index = _.indexOf(your_array, _.find(your_array, function (d) {
    return d === true;
}));

文档:

于 2013-09-17T03:12:19.187 回答
4

从 ES 2015 开始,Array.prototype.find()提供了这个确切的功能。

对于不支持此功能的浏览器,Mozilla 开发者网络提供了一个polyfill(粘贴在下面):

if (!Array.prototype.find) {
  Array.prototype.find = function(predicate) {
    if (this === null) {
      throw new TypeError('Array.prototype.find called on null or undefined');
    }
    if (typeof predicate !== 'function') {
      throw new TypeError('predicate must be a function');
    }
    var list = Object(this);
    var length = list.length >>> 0;
    var thisArg = arguments[1];
    var value;

    for (var i = 0; i < length; i++) {
      value = list[i];
      if (predicate.call(thisArg, value, i, list)) {
        return value;
      }
    }
    return undefined;
  };
}
于 2016-05-02T18:48:41.037 回答
4
foundElement = myArray[myArray.findIndex(element => //condition here)];
于 2019-04-04T09:29:28.383 回答
3

Array.prototype.find() 就是这样做的,更多信息:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

于 2016-02-22T16:28:03.183 回答
2

findIndex像以前写的一样使用。这是完整的示例:

function find(arr, predicate) {
    foundIndex = arr.findIndex(predicate);
    return foundIndex !== -1 ? arr[foundIndex] : null;
}

用法如下(我们想在数组中找到第一个具有属性的元素id === 1)。

var firstElement = find(arr, e => e.id === 1);
于 2020-11-06T08:46:07.093 回答
0

我从互联网上的多个来源获得灵感,得出以下解决方案。想要同时考虑一些默认值,并提供一种方法来比较每个条目以找到可以解决的通用方法。

用法:(赋予值“第二”)

var defaultItemValue = { id: -1, name: "Undefined" };
var containers: Container[] = [{ id: 1, name: "First" }, { id: 2, name: "Second" }];
GetContainer(2).name;

执行:

class Container {
    id: number;
    name: string;
}

public GetContainer(containerId: number): Container {
  var comparator = (item: Container): boolean => {
      return item.id == containerId;
    };
    return this.Get<Container>(this.containers, comparator, this.defaultItemValue);
  }

private Get<T>(array: T[], comparator: (item: T) => boolean, defaultValue: T): T {
  var found: T = null;
  array.some(function(element, index) {
    if (comparator(element)) {
      found = element;
      return true;
    }
  });

  if (!found) {
    found = defaultValue;
  }

  return found;
}
于 2019-08-07T16:49:13.520 回答
-2

Javascript 中没有执行此搜索的内置函数。

如果你使用 jQuery,你可以做一个jQuery.inArray(element,array).

于 2012-05-04T23:22:55.177 回答
-2

一种不太优雅的方式,将throw所有正确的错误消息(基于Array.prototype.filter)但将停止迭代第一个结果是

function findFirst(arr, test, context) {
    var Result = function (v, i) {this.value = v; this.index = i;};
    try {
        Array.prototype.filter.call(arr, function (v, i, a) {
            if (test(v, i, a)) throw new Result(v, i);
        }, context);
    } catch (e) {
        if (e instanceof Result) return e;
        throw e;
    }
}

然后例子是

findFirst([-2, -1, 0, 1, 2, 3], function (e) {return e > 1 && e % 2;});
// Result {value: 3, index: 5}
findFirst([0, 1, 2, 3], 0);               // bad function param
// TypeError: number is not a function
findFirst(0, function () {return true;}); // bad arr param
// undefined
findFirst([1], function (e) {return 0;}); // no match
// undefined

filter通过使用结束来工作throw

于 2013-08-29T18:46:06.087 回答