【问题标题】:In C# .NET 2.0, what's an easy way to do a foreach in reverse?在 C# .NET 2.0 中,反向执行 foreach 的简单方法是什么?
【发布时间】:2010-09-10 02:51:41
【问题描述】:

假设我有一个 Dictionary 对象:

Dictionary myDictionary<int, SomeObject> = new Dictionary<string, SomeObject>();

现在我想以相反的顺序遍历字典。我不能使用简单的 for 循环,因为我不知道字典的键。 foreach 很简单:

foreach (SomeObject object in myDictionary.Values)
{
    // Do stuff to object
}

但是我怎样才能反过来执行呢?

【问题讨论】:

    标签: c# .net collections iteration


    【解决方案1】:

    字典或任何其他形式的哈希表没有排序。所以你想做的事是没有意义的:)

    【讨论】:

    • 如果您想要哈希表类型查找以及 arraylist 样式序列排序,请使用 SortedList。有人已经贴了代码sn-p。
    • @DaveVandenEynde:我猜如果随机性足够确定的话。
    • 嗯,我的猜测是字典是按哈希值排序的。这是否有用是完全不同的问题。但随机,它不是。
    【解决方案2】:

    这将是一个Dictionary&lt;int, SomeObject&gt; myDictionary,你可以这样做:

    foreach(SomeObject _object in myDictionary.Values.Reverse())
    {
    }
    

    【讨论】:

    • Reverse() 函数在 .net 2.0 中不可用
    【解决方案3】:

    如果排序是最重要的,您可以使用 Stack 并创建一个简单的结构来存储您的 int、Object 对。

    【讨论】:

      【解决方案4】:

      如果您有 .NET 3.5,则可以在 IEnumerables 上使用 .Reverse() 扩展方法。例如:

      foreach (object o in myDictionary.Values.Reverse())
      {
           // Do stuff to object
      }
      

      【讨论】:

      • 你需要参考 --> 使用 System.Linq;
      【解决方案5】:

      我在 .NET 2.0 中能想到的唯一方法是首先将所有值复制到一个列表中,反转该列表,然后在该列表上运行 foreach:

      Dictionary<int, object> d;
      List<object> tmplist;
      foreach (object o in d.Values) tmplist.Add(s);
      tmplist.Reverse();
      foreach (object o in tmplist) {
          //Do stuff
      }
      

      【讨论】:

        【解决方案6】:

        我同意@leppie 的观点,但认为你应该得到这个问题的一般答案。可能是您的意思是一般问题,但意外选择了错误的数据结构。字典中值的顺序应该被认为是特定于实现的;根据文档,它始终与键的顺序相同,但此顺序也未指定。

        无论如何,没有一种简单的方法可以让foreach 反向工作。使用类的枚举器是语法糖,枚举器只能在一个方向移动。从技术上讲,答案可能是“反转集合,然后枚举”,但我认为这是您只需要使用“向后”for 循环的情况:

        for (int i = myCollection.Length - 1; i >= 0; i--)
        {
            // do something
        }

        【讨论】:

        • 这不起作用,因为 Dictionary 类的“Values”属性返回的集合没有索引器。
        【解决方案7】:

        如果你想要一个字典类型的集合,但你需要维护插入顺序,你可以查看 KeyedCollection here

        它是字典和列表的合并。这样您就可以通过键或插入索引访问集合中的元素。

        唯一的问题是存储在集合中的元素是否必须有一个 int 键。如果您可以将其更改为字符串或其他类型(Guid Mabye)。因为 collection1 将搜索 1 的键而不是 1 的索引。

        【讨论】:

          【解决方案8】:

          一个标准的for 循环是最好的。您不必担心反转集合的处理开销。

          【讨论】:

            【解决方案9】:

            我会使用 SortedList 而不是字典。您仍然可以通过 Key 访问它,但您也可以通过索引访问它。

            SortedList sCol = new SortedList();
            
            sCol.Add("bee", "Some extended string matching bee");
            sCol.Add("ay", "value matching ay");
            sCol.Add("cee", "Just a standard cee");
            
            // Go through it backwards.
            for (int i = sCol.Count - 1; i >=0 ; i--)
                Console.WriteLine("sCol[" + i.ToString() + "] = " + sCol.GetByIndex(i));
            
            // Reference By Key
            foreach (string i in sCol.Keys)
                Console.WriteLine("sCol[" + i + "] = " + sCol[i]);
            
            // Enumerate all values
            foreach (string i in sCol.Values)
                Console.WriteLine(i);
            

            值得注意的是,排序列表存储的键/值对仅按键排序。

            【讨论】:

              【解决方案10】:

              实际上,在 C# 2.0 中,您可以创建自己的迭代器来反向遍历容器。然后,您可以在 foreach 语句中使用该迭代器。但是您的迭代器首先必须有一种导航容器的方法。如果它是一个简单的数组,它可以像这样倒退:

              static IEnumerable<T> CreateReverseIterator<T>(IList<T> list)
              {
                  int count = list.Count;
                  for (int i = count - 1; i >= 0; --i)
                  {
                      yield return list[i];
                  }
              }
              

              但是你当然不能用 Dictionary 来做到这一点,因为它没有实现 IList 或提供索引器。说字典没有顺序是不正确的:它当然有顺序。如果您知道它是什么,该命令甚至会很有用。

              对于您的问题的解决方案:我会说将元素复制到一个数组,然后使用上述方法反向遍历它。像这样:

              static void Main(string[] args)
              {
                  Dictionary<int, string> dict = new Dictionary<int, string>();
              
                  dict[1] = "value1";
                  dict[2] = "value2";
                  dict[3] = "value3";
              
                  foreach (KeyValuePair<int, string> item in dict)
                  {
                      Console.WriteLine("Key : {0}, Value: {1}", new object[] { item.Key, item.Value });
                  }
              
                  string[] values = new string[dict.Values.Count];
                  dict.Values.CopyTo(values, 0);
              
                  foreach (string value in CreateReverseIterator(values))
                  {
                      Console.WriteLine("Value: {0}", value);
                  }
              
              }
              

              将值复制到数组可能看起来是个坏主意,但根据值的类型,它并没有那么糟糕。您可能只是在复制参考资料!

              【讨论】:

                【解决方案11】:

                您可以使用LinqBridge 在.NET 2.0 中使用LINQ to Objects Enumerable.Reverse() 函数。

                【讨论】:

                  【解决方案12】:

                  字面答案:

                  Dictionary<int, SomeObject>  myDictionary = new Dictionary<int, SomeObject>();
                  
                  foreach (var pair in myDictionary.OrderByDescending(i => i.Key))
                  {
                      //Observe pair.Key
                      //Do stuff to pair.Value
                  }
                  

                  【讨论】:

                    【解决方案13】:

                    如果您没有 .NET 3.5 和 Reverse 扩展方法,您可以实现自己的。我猜它可能会生成一个中间列表(必要时)并反向迭代它,如下所示:

                    public static IEnumerable<T> Reverse<T>(IEnumerable<T> items)
                    {
                        IList<T> list = items as IList<T>;
                        if (list == null) list = new List<T>(items);
                        for (int i = list.Count - 1; i >= 0; i-- )
                        {
                            yield return list[i];
                        }
                    }
                    

                    【讨论】:

                      【解决方案14】:
                      foreach (Sample in Samples)
                      
                      try the following:
                      
                      Int32 nEndingSample = Samples.Count - 1;
                      
                      for (i = nEndingSample; i >= 0; i--)
                      {
                           x = Samples[i].x;
                           y = Samples[i].y;
                      }
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 2012-06-20
                        • 2010-09-21
                        • 2012-06-01
                        • 1970-01-01
                        • 2018-01-21
                        • 1970-01-01
                        • 2010-09-07
                        相关资源
                        最近更新 更多