如何在 JavaScript 中找到匹配布尔条件的数组的第一个元素?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10457264/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:23:31  来源:igfitidea点击:

How to find first element of array matching a boolean condition in JavaScript?

javascriptarrays

提问by Jakub P.

I'm wondering if there's a known, built-in/elegant way to find the first element of a JS array matching a given condition. A C# equivalent would be List.Find.

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

So far I've been using a two-function combo like this:

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

// 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);
};

And then I can use:

然后我可以使用:

var result = someArray.findFirst(isNotNullNorUndefined);

But since there are so many functional-style array methods in ECMAScript, perhaps there's something out there already like this? I imagine lots of people have to implement stuff like this all the time...

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

采纳答案by Bergi

Since ES6 there is the native findmethodfor arrays; this stops enumerating the array once it finds the first match and returns the value.

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

const result = someArray.find(isNotNullNorUndefined);


Old answer:

旧答案:

I have to post an answer to stop these filtersuggestions :-)

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

since there are so many functional-style array methods in ECMAScript, perhaps there's something out there already like this?

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

You can use the someArray methodto iterate the array until a condition is met (and then stop). Unfortunately it will only return whether the condition was met once, not by which element (or at what index) it was met. So we have to amend it a little:

您可以使用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);

回答by Mark Amery

As of ECMAScript 6, you can use Array.prototype.findfor this. This is implemented and working in Firefox (25.0), Chrome (45.0), Edge (12), and Safari (7.1), but not in Internet Explorer or a bunch of other old or uncommon platforms.

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

For example, the expression below evaluates to 106.

例如,下面的表达式计算结果为106

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

If you want to use this right now but need support for IE or other unsupporting browsers, you can use a shim. I recommend the es6-shim. MDN also offers a shimif for some reason you don't want to put the whole es6-shim into your project. For maximum compatibility you want the es6-shim, because unlike the MDN version it detects buggy native implementations of findand overwrites them (see the comment that begins "Work around bugs in Array#find and Array#findIndex"and the lines immediately following it).

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

回答by Phil Mander

What about using filterand getting the first index from the resulting array?

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

var result = someArray.filter(isNotNullNorUndefined)[0];

回答by Ja?ck

It should be clear by now that JavaScript offers no such solution natively; here are the closest two derivatives, the most useful first:

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

  1. Array.prototype.some(fn)offers the desired behaviour of stopping when a condition is met, but returns only whether an element is present; it's not hard to apply some trickery, such as the solution offered by Bergi's answer.

  2. Array.prototype.filter(fn)[0]makes for a great one-liner but is the least efficient, because you throw away N - 1elements just to get what you need.

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

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

Traditional search methods in JavaScript are characterized by returning the index of the found element instead of the element itself or -1. This avoids having to choose a return value from the domain of all possible types; an index can only be a number and negative values are invalid.

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

Both solutions above don't support offset searching either, so I've decided to write this:

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

(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

回答by Willem van der Veen

Summary:

概括:

  • For finding the first element in an array which matches a boolean condition we can use the ES6find()
  • find()is located on Array.prototypeso it can be used on every array.
  • find()takes a callback where a booleancondition is tested. The function returns the value(not the index!)
  • 要查找数组中与布尔条件匹配的第一个元素,我们可以使用 ES6find()
  • find()位于 上,Array.prototype因此可以在每个阵列上使用。
  • find()接受一个boolean条件被测试的回调。该函数返回(不是索引!)

Example:

例子:

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

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

console.log(found);   //  56

回答by Matt Woelk

If you're using underscore.jsyou can use its findand indexOffunctions to get exactly what you want:

如果您正在使用,underscore.js您可以使用它的findindexOf函数来获得您想要的东西:

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

Documentation:

文档:

回答by Kevin Lee Garner

As of ES 2015, Array.prototype.find()provides for this exact functionality.

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

For browsers that do not support this feature, the Mozilla Developer Network has provided a polyfill(pasted below):

对于不支持此功能的浏览器,Mozilla Developer Network 提供了一个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;
  };
}

回答by Dan Ochiana

回答by dotista2008

foundElement = myArray[myArray.findIndex(element => //condition here)];

回答by Henrik

I have got inspiration from multiple sources on the internet to derive into the solution below. Wanted to take into account both some default value and to provide a way to compare each entry for a generic approach which this solves.

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

Usage: (giving value "Second")

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

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

Implementation:

执行:

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;
}