假设我有一个 Dictionary 对象:

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

现在我想以相反的顺序迭代字典。我无法使用简单的 for 循环,因为我不知道字典的键。A foreach 简单:

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

但我怎样才能反向执行此操作呢?

有帮助吗?

解决方案

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

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

其他提示

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

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

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

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

}

将值复制到数组似乎是一个坏主意,但根据值的类型,它实际上并没有那么糟糕。您可能只是复制参考资料!

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

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

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

如果您没有 .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];
    }
}

那将是一个 Dictionary<int, SomeObject> myDictionary, ,你可以这样做:

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

我能想到的唯一方法 .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
}

如果顺序最重要,您可以创建一个堆栈并创建一个简单的结构来存储 int、对象对。

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

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

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

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

您可以使用 LINQ 到对象 .NET 2.0 中的 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
}
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;
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top