【问题标题】:how do I check if an entity is the first element of a foreach loop如何检查实体是否是 foreach 循环的第一个元素
【发布时间】:2011-04-02 23:21:43
【问题描述】:

假设我有一个foreach 循环。

我必须对循环的第一个对象做一些与其他任何对象无关的事情。

如何检查当前循环中的项目是否是第一个对象。

【问题讨论】:

    标签: c# .net foreach


    【解决方案1】:

    有几种方法可以做到这一点。

    1. 改用for 循环
    2. 设置布尔标志
    3. 使用 Linq 获取 list.First(),然后通过 list.Skip(1) 获取 foreach

    【讨论】:

      【解决方案2】:

      在我看来这是最简单的方法

      foreach (var item in list)
      {
          if((list.IndexOf(item) == 0)
          {
              // first
          }
          // others
      }
      

      【讨论】:

      • 这可能是最简单的方法,但是非常昂贵。如果列表是任意的IEnumerable,则复杂度在 O(n) 之内,这在每次迭代中都会执行很多开销。
      【解决方案3】:

      我喜欢 Linq 方式,但没有 Skip(1),这样您也可以将它用于列表中的最后一项,并且您的代码保持干净恕我直言 :)

      foreach(var item in items)
      {
          if (items.First()==item)
              item.firstStuff();
      
          else if (items.Last() == item)
              item.lastStuff();
      
          item.otherStuff();
      }
      

      【讨论】:

      • 我不喜欢这种方法,因为它并不完全准确。例如,如果一个项目不止一次出现,并且也是第一个或最后一个项目,那么您将多次触发第一个或最后一个条件。或者如果某些项目具有相等性,它们也可以多次触发它。
      • @Sahuagin 问题是关于测试项目是否首先。如果您清除 else if 部分,这意味着您正在测试项目是否只是第一个,您的正当担忧将得到缓解。
      【解决方案4】:

      这更像是获取数组中每个对象的索引的通用解决方案。如果是第一个,应该进行测试。

              List<String> entries = new List<string>();
              entries.Add("zero");
              entries.Add("one");
              entries.Add("two");
      
              Dictionary<int, String> numberedEntries = new Dictionary<int, string>();
              int i = 0;
              entries.ForEach(x => numberedEntries.Add(i++, x));
              foreach (KeyValuePair<int, String> pair in numberedEntries) {
                  Console.WriteLine(pair.Key + ": " + pair.Value);
              }
      

      在此设置中,KeyValuePair 的键是索引,值是该索引处的对象,在我的示例中是字符串,但任何对象都可以放置在那里。它增加了一点开销,但可用于在需要时确定列表索引中的任何对象。

      【讨论】:

      • 闻起来像 Python 的 dict.__items__ 我喜欢!
      【解决方案5】:

      这是一个高效的解决方案:

      using (var erator = enumerable.GetEnumerator())
      {
          if (erator.MoveNext())
          {
              DoActionOnFirst(erator.Current);
      
              while (erator.MoveNext())
                  DoActionOnOther(erator.Current);
          }
      }
      

      编辑:这是一个 LINQ:

      if (enumerable.Any())
          {
              DoActionOnFirst(enumerable.First());
      
              foreach (var item in enumerable.Skip(1))
                  DoActionOnOther(item);
          }
      

      编辑:如果对项目的操作具有可分配给Func&lt;TItem, TResult&gt; 的签名,您可以这样做:

      enumerable.Select((item, index) => index == 0 ? GetResultFromFirstItem(item) : GetResultFromOtherItem(item));
      

      【讨论】:

      • 虽然这在技术上满足要求,但它的可读性明显低于使用“第一个”标志来指示其他人发布的内容。
      • @Paul:效率更高,但我不明白为什么它的可读性明显降低。
      • 不确定与使用“第一”标志相比如何更有效。
      • @Babar 使用此解决方案,无需在每次迭代时评估变量
      • 对于 LINQ 答案,这应该是正确答案,因为它比使用标志更优雅。
      【解决方案6】:

      试试这个

      bool IsFirst = true;
      
      foreach(DataRow dr in dt.Rows)
      {
          if (IsFirst)
          {
              // do some thing
              IsFirst = false;
          }    
      }
      

      【讨论】:

        【解决方案7】:

        什么都想不出来

        var processedFirst = false;
        foreach(var x in items) {
            if(!processedFirst) {
                ProcessFirst(x);
                processedFirst = true;
            }
        

        【讨论】:

          【解决方案8】:
          bool first = true;
          foreach(var foo in bar)
          {
            if (first)
            {
              // do something to your first item
              first = false;
            }
            // do something else to the rest
          }
          

          【讨论】:

          • grr,不够快!没有看到 geofftnz 的帖子。
          • 这是 StackOverflow 专利的简单问题竞赛 :)
          【解决方案9】:

          类似这样的:

          bool first = true;
          
          foreach(var item in items)
          {
              if (first)
              {
                  item.firstStuff();
                  first = false;
              }
              item.otherStuff();
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-08-10
            • 1970-01-01
            • 2011-04-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-02
            • 1970-01-01
            相关资源
            最近更新 更多