17

假设我有一个 Dictionary 对象:

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

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

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

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

4

14 回答 14

28

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

于 2008-09-17T13:02:20.647 回答
20

我会使用 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);

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

于 2008-09-17T13:17:01.097 回答
18

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

foreach (object o in myDictionary.Values.Reverse())
{
     // Do stuff to object
}
于 2008-09-17T13:05:53.103 回答
4

实际上,在 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);
    }

}

将值复制到数组中似乎是个坏主意,但根据值的类型,它并不是那么糟糕。您可能只是在复制参考!

于 2008-09-17T13:24:09.550 回答
3

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

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

for (int i = myCollection.Length - 1; i >= 0; i--)
{
    // do something
}
于 2008-09-17T13:09:43.313 回答
3

如果您没有 .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];
    }
}
于 2008-09-17T14:14:52.377 回答
1

那将是 a Dictionary<int, SomeObject> myDictionary,您可以通过以下方式进行:

foreach(SomeObject _object in myDictionary.Values.Reverse())
{
}
于 2008-09-17T13:05:45.960 回答
1

在.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
}
于 2008-09-17T13:06:08.827 回答
1

字面答案:

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
}
于 2008-09-17T13:54:52.127 回答
0

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

于 2008-09-17T13:05:52.637 回答
0

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

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

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

于 2008-09-17T13:13:10.887 回答
0

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

于 2008-09-17T13:15:58.523 回答
0

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

于 2008-09-17T13:42:39.567 回答
-2
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;
}
于 2012-09-01T03:54:16.940 回答