在C#.NET 2.0中,逆向进行foreach的简单方法是什么?
可以说我有一个Dictionary对象:
Dictionary myDictionary<int, SomeObject> = new Dictionary<string, SomeObject>();
现在,我想以相反的顺序遍历字典。我不能使用简单的for循环,因为我不知道字典的键。 foreach很简单:
foreach (SomeObject object in myDictionary.Values) { // Do stuff to object }
但是,我该如何反向执行呢?
解决方案
回答
字典或者任何其他形式的哈希表没有顺序。所以你想做的是没有意义的:)
回答
那将是Dictionary <int,SomeObject> myDictionary
,我们可以通过以下方式实现:
foreach(SomeObject _object in myDictionary.Values.Reverse()) { }
回答
如果排序最重要,则可以堆栈并创建一个简单的结构来存储int,Object对。
回答
如果我们具有.NET 3.5,则可以在IEnumerables上使用.Reverse()扩展方法。例如:
foeach (SomeObject o in myDictionary.Values.Reverse()) { // Do stuff to object }
回答
我可以在.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 }
回答
我同意@leppie,但认为我们总体上应该得到该问题的答案。可能是意思是笼统地问了这个问题,但不小心选择了一个错误的数据结构。字典中值的顺序应被视为特定于实现的;根据文档,它始终与键顺序相同,但是此顺序也未指定。
无论如何,没有一种简单的方法可以使" foreach"反向工作。使用该类的枚举器是语法糖,并且枚举器只能沿一个方向传播。从技术上讲,答案可能是"反转集合,然后枚举",但是我认为在这种情况下,我们只需要对循环使用"向后"即可:
for (int i = myCollection.Length - 1; i >= 0; i--) { // do something }
回答
如果我们需要字典类型集合,但需要维护插入顺序,则可以查看KeyedCollection
这里
它是字典和列表之间的合并。这样,我们可以通过键或者插入索引访问集合中的元素。
唯一的难题是,存储在集合中的元素是否必须具有int键。如果可以将其更改为字符串或者其他类型(Guid Mabye)。由于collection1将搜索键1而不是索引1.
回答
标准的" for"循环将是最好的。我们不必担心反转集合的处理开销。
回答
我会使用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);
值得注意的是,已排序列表仅存储按键排序的键/值对。
回答
实际上,在C2.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); } }
将值复制到数组似乎不是一个好主意,但是根据值的类型,它并没有那么糟糕。我们可能只是在复制参考!
回答
我们可以使用LinqBridge在.NET 2.0中使用LINQtoObjects Enumerable.Reverse()函数。
回答
字面答案:
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 }
回答
如果我们没有.NET 3.5,因此没有反向扩展方法,则可以实现自己的方法。我猜想它可能会生成一个中间列表(必要时)并以相反的方式对其进行迭代,如下所示:
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]; } }