【问题标题】:How to work with extra int parameter in LINQ Where()如何在 LINQ Where() 中使用额外的 int 参数
【发布时间】:2016-01-09 08:50:50
【问题描述】:

请注意,这不是关于delegates 一般是什么的问题。另外,我已经看到docs 没有得到任何明智。

在 LINQ 中,我可以使用类似的东西。

using(Model model = new Model())
{
   return model.Things
               .Where(thing => thing.IsGood);
}

我可以看到返回类型(运算符的左侧对象)是Thing 类型,而条件(运算符的右侧对象)是bool 类型。 Intellisense 告诉我,我可以从这两个中进行选择,而我被第二个弄糊涂了。

Func<Thing, bool>  
Func<Thing, int, bool>

我假设 lambda 运算符只是实际调用的语法糖。那是对的吗?如果是这样,那个整数在那里做什么以及如何指定它?

【问题讨论】:

  • Where 的文档回答了你所有的问题!
  • 它是循环中元素的索引。看例子here
  • 它可以让你在where中查看当前正在处理的项目的索引。就这么简单。
  • @RahulSingh 真的没有。我已经编辑了这个问题。不是说它不存在。我是说我已经看过了,但我仍然有同样的问题......

标签: c# linq lambda where func


【解决方案1】:

来自docs for this overload

谓词

输入:System.Func&lt;TSource, Int32, Boolean&gt;

测试每个源元素的条件的函数;函数的第二个参数表示源元素的索引。

正如这所暗示的,整数是元素的索引。

所以,

var everyTwo = input.Where((c, i) => i % 2 == 0);

例如,仅返回每隔一个元素。上面链接的文档有一个稍微复杂的用例示例,它涉及两个参数。

我不确定这是否只是一个错字,但您链接到的文档似乎是针对不包含此参数的重载,这可能解释了为什么您找不到它的解释。

【讨论】:

    【解决方案2】:

    正如 cmets 中已经提到的,文档指出第二个重载:-

    根据谓词过滤一系列值。每个元素的 index用于谓词函数的逻辑。

    这里是reference code,我想它会让你明白:-

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, 
                                                       Func<TSource, int, bool> predicate) 
    {
        if (source == null) throw Error.ArgumentNull("source");
        if (predicate == null) throw Error.ArgumentNull("predicate");
        return WhereIterator<TSource>(source, predicate);
    }
    
    static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, 
                                                       Func<TSource, int, bool> predicate) 
    {
       int index = -1;
       foreach (TSource element in source) {
           checked { index++; }
           if (predicate(element, index)) yield return element;
       }
    }
    

    您可以在foreach 语句中看到我们提供的索引是如何使用的。因此,我们可以将谓词用作:-

    .Where((thing, index) => thing.SomeIntProperty <= index * 2);
    

    【讨论】:

      【解决方案3】:

      用一个例子来说明,而不是简单地引用 MSDN 帮助页面:

      获取此代码:

      var list = new List<string> { "a", "b", "c" }
      var index = 0;
      foreach (var item in list)
      {
          if (item == "b" && index == 1) {
              Console.WriteLine(item);
          }
          index++;
      }
      

      变成

      var list = new List<string> { "a", "b", "c" }
      
      var items = list.Where((item, index) => item == "b" && index == 1)
      
      foreach (var item in items) {
          Console.WriteLine(item);
      }
      

      (您可以使用其他 linq 命令进行 writeline 等,这是为了说明 Where

      【讨论】:

      • 显示 foreach 版本以与 LINQ 版本进行比较非常有用。聪明的主意。 +1
      【解决方案4】:

      正如MSDN中所说:

      根据谓词过滤一系列值。每个元素的 index用于谓词函数的逻辑。

      什么时候需要这个?例如,您可能需要所有具有偶数索引的元素:

      return model.Things
          .Where((thing, index) => index % 2 == 0);
      

      此外,将来您可以使用this web site 为我们提供.net 源代码,从而更深入地发现和学习这些东西。比如这里是Where()方法的overlaod的实现:

       public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
                  if (source == null) throw Error.ArgumentNull("source");
                  if (predicate == null) throw Error.ArgumentNull("predicate");
                  return WhereIterator<TSource>(source, predicate);
              }
      

      我们可以看到它返回WhereIterator方法:

      static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, int, bool> predicate) {
                  int index = -1;
                  foreach (TSource element in source) {
                      checked { index++; }
                      if (predicate(element, index)) yield return element;
                  }
              }
      

      我们可以看到实际上Linq使用foreach循环,通过将index变量加一来获取当前元素的索引。

      【讨论】:

        【解决方案5】:

        Where 上有两篇 MSDN 文章。您链接到的The onethis one

        使用语法如下。

        using(Model model = new Model())
        {
          return model.Things
            .Where((thing, counter) => thing.IsGood < counter);
        }
        

        如您所见,它在 这种 特殊情况下没有什么意义,而且我从来不需要使用它。然而,如果需要,它就在那里。您可以在提供的链接中找到示例。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多