【问题标题】:JavaScript/jQuery equivalent of LINQ Any()JavaScript/jQuery 等效于 LINQ Any()
【发布时间】:2011-08-22 11:27:58
【问题描述】:

在 JavaScript 或 jQuery 中是否有 IEnumerable.Any(Predicate<T>) 的等价物?

我正在验证一个项目列表,如果检测到错误,我想尽早中断。我可以使用$.each 做到这一点,但我需要使用外部标志来查看是否确实找到了该项目:

var found = false;
$.each(array, function(i) {
    if (notValid(array[i])) {
        found = true;
    }
    return !found;
});

有什么更好的方法?我不喜欢在 JavaScript 数组中使用普通的 for,因为它会迭代所有成员,而不仅仅是值。

【问题讨论】:

    标签: javascript jquery foreach ienumerable any


    【解决方案1】:

    如今,您实际上可以使用 Array.prototype.some(在 ES5 中指定)来获得相同的效果:

    array.some(function(item) {
        return notValid(item);
    });
    

    【讨论】:

    • 快速总结:some() 对数组中存在的每个元素执行一次回调函数,直到找到一个回调函数返回真值。如果找到这样的元素,some() 立即返回 true。否则,some() 返回 false。
    • 如果你能用,这就是正确的答案。它是 Linq.Any() 的等效函数
    • 如果你需要兼容 IE8,那么这不是一个选项。
    • 更新:在 ES6 / ECMAScript 2015 中,您可以使用 myArray.some(c=>c) 来准确模仿 LINQ 对 .Any() 的作用。请注意,在 LINQ 中 .Any() 方法不需要委托,而 .some() 需要委托。尝试在没有委托的情况下调用 .some() 将导致错误,因为委托将未定义。
    【解决方案2】:

    您可以使用接受谓词的 jQuery is 函数的变体:

    $(array).is(function(index) {
        return notValid(this);
    });
    

    【讨论】:

    • 我认为当用于array 时,您应该避免在is 函数中使用this。因为你不会得到原始类型(所以使用“===”的比较会失败)。我会改用array[i]。看到这个:jsfiddle.net/BYjcu/3
    • 这很有趣(我的fiddle to confirm),但我的直觉反应是避免这种方法,因为它在不是 jQuery 选择(本机数组)的集合上运行选择函数 $.fn.is .如果有像$.is 这样的实用功能,我会觉得更安全,但这似乎是一个未记录的“功能”
    • AFAIK jQuery 选择 原生数组(或者至少他们使用Array.prototype),并且可能有足够的代码依赖它,它永远不会改变。这句话,这个答案已经快六年了。这些天你应该使用附近显示的原生 ES5 方法,或者像 LoDash/Underscore/等。具有专门用于处理原生 JS 数组的 API。
    • 你说得对,我没有注意到这个答案的日期。对此感到抱歉(现在我无法撤消我的反对票!)
    【解决方案3】:

    Xion 的回答是正确的。扩展他的答案:

    jQuery 的 .is(function) 与 .NET 的 IEnumerable.Any(Predicate<T>) 具有相同的行为。

    来自http://docs.jquery.com/is

    根据表达式检查当前选择,如果选择的至少一个元素适合给定的表达式,则返回 true。

    【讨论】:

    • 这应该是对他们答案的评论或编辑吗?似乎只同意那个答案,添加了一些上下文?
    【解决方案4】:

    您应该使用普通的for 循环(不是for ... in),它只会循环遍历数组元素。

    【讨论】:

    • *可以(我想你是想说)
    • @Simon_Weaver:不;他不应该使用for in来迭代数组。
    • @SLaks,你误解了 Simon_Weaver 的评论! “您可以使用普通的 for 循环。”而不是“你应该...”
    • 嗯,它肯定说应该就在文本中。当字面上写在那里时,你不能说他们被误解了。
    【解决方案5】:

    您可以使用 array.filter(IE 9+ 请参阅下面的链接了解更多详细信息)

    [].filter(function(){ return true|false ;}).length > 0;
    

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

    【讨论】:

      【解决方案6】:

      我建议您尝试 JavaScript for in 循环。但是,请注意语法与使用 .net IEnumerable 获得的语法完全不同。这是一个小的说明性代码示例。

      var names = ['Alice','Bob','Charlie','David'];
      for (x in names)
      {
          var name = names[x];
          alert('Hello, ' + name);
      }
      
      var cards = { HoleCard: 'Ace of Spades', VisibleCard='Five of Hearts' };
      for (x in cards)
      {
          var position = x;
          var card = card[x];
          alert('I have a card: ' + position + ': ' + card);
      }
      

      【讨论】:

      • 我相信 OP 想用 plain for (...) 迭代其所有成员for in 的使用有时可以 yield unexpected results (如果Array.prototype 已扩展,或者如果您隐式调整数组大小)。
      【解决方案7】:

      死灵术。
      如果你不能使用 array.some,你可以在 TypeScript 中创建你自己的函数:

      interface selectorCallback_t<TSource> 
      {
          (item: TSource): boolean;
      }
      
      
      function Any<TSource>(source: TSource[], predicate: selectorCallback_t<TSource> )
      {
          if (source == null)
              throw new Error("ArgumentNullException: source");
          if (predicate == null)
              throw new Error("ArgumentNullException: predicate");
      
          for (let i = 0; i < source.length; ++i)
          {
              if (predicate(source[i]))
                  return true;
          }
      
          return false;
      } // End Function Any
      

      转译为

      function Any(source, predicate) 
       {
          if (source == null)
              throw new Error("ArgumentNullException: source");
          if (predicate == null)
              throw new Error("ArgumentNullException: predicate");
          for (var i = 0; i < source.length; ++i) 
          {
              if (predicate(source[i]))
                  return true;
          }
          return false;
      }
      

      用法:

      var names = ['Alice','Bob','Charlie','David'];
      Any(names, x => x === 'Alice');
      

      【讨论】:

        【解决方案8】:

        我建议你使用$.grep() 方法。非常接近IEnumerable.Any(Predicate&lt;T&gt;)

        $.grep(array, function(n, i) {
          return (n == 5);
        });
        

        这里有一个工作示例:http://jsfiddle.net/ErickPetru/BYjcu/

        2021 年更新

        这个答案是 10 多年前发布的,所以强调这一点很重要:

        1. 当它发布时,它是一个完全合理的解决方案,因为当时 JavaScript 没有原生的东西可以通过单个函数调用来解决这个问题;
        2. 原始问题带有 jQ​​uery 标签,因此基于 jQuery 的答案不仅是预期的,而且是必须的。因此投反对票根本没有意义。
        3. 从那时起,JavaScript 世界发生了很大的变化,因此,如果您不喜欢 jQuery,请使用更新的解决方案!这个是出于历史目的,并作为旧需求的参考,也许有人在使用遗留代码时仍然觉得有用。

        【讨论】:

        • 其实$.grep()更像FindAll(Predicate&lt;T&gt;)
        • @Groo:我没说Any(Predicate&lt;T&gt;)是最接近grep()的方法,只是非常接近。我同意FindAll(Predicate&lt;T&gt;) 更接近它。但两者都在附近。
        猜你喜欢
        • 1970-01-01
        • 2018-01-02
        • 2013-09-27
        • 1970-01-01
        • 2020-10-28
        • 2018-08-05
        • 2013-05-05
        • 2011-01-24
        • 1970-01-01
        相关资源
        最近更新 更多