4

我有一本字典,比如

Dictionary<Foo,String> fooDict

我逐步浏览字典中的所有内容,例如

foreach (Foo foo in fooDict.Keys)
    MessageBox.show(fooDict[foo]);

它按照将 foo 添加到字典中的顺序执行此操作,因此添加的第一个项目是返回的第一个 foo。

如何更改基数,例如,添加的第三个 foo 将是返回的第二个 foo?换句话说,我想改变它的“索引”。

4

5 回答 5

8

如果您阅读 MSDN 上的文档,您会看到:

“退货的顺序未定义。”

您无法保证订单,因为 Dictionary 不是列表或数组。它旨在通过键查找值,任何迭代值的能力都只是一种方便,但顺序不是您应该依赖的行为。

于 2008-09-24T23:45:24.697 回答
5

您可能对命名空间中的OrderedDicationary类感兴趣System.Collections.Specialized

如果您查看最底部的评论,则来自 MSFT 的某人发布了此有趣的注释:

这种类型实际上是错误命名的;它不是一个“有序”字典,而是一个“索引”字典。虽然,今天没有这种类型的等效通用版本,但如果我们将来添加一个,我们很可能会命名为“IndexedDictionary”类型。

我认为从此类派生并制作 OrderedDictionary 的通用版本将是微不足道的。

于 2008-09-25T01:08:08.103 回答
0

在该领域没有受过充分的教育来正确回答这个问题,但我感觉字典会根据键对值进行排序,以便执行快速键搜索。这表明字典是根据键比较按键值排序的。但是,在查看对象方法时,我假设它们使用哈希码来比较不同的对象,因为对用于键的类型没有要求。这只是一个猜测。更有知识的人应该填写更多细节。

当字典的目的是使用任意类型进行索引时,您为什么对操作字典的“索引”感兴趣?

于 2008-09-24T23:42:06.017 回答
0

我不知道是否有人会发现这很有用,但这是我最终弄清楚的。它似乎有效(我的意思是它不会抛出任何异常),但我仍然无法测试它是否像我希望的那样有效。不过,我以前也做过类似的事情。

        public void sortSections()
    {
        //OMG THIS IS UGLY!!!
        KeyValuePair<ListViewItem, TextSection>[] sortable = textSecs.ToArray();
        IOrderedEnumerable<KeyValuePair<ListViewItem, TextSection>> sorted = sortable.OrderBy(kvp => kvp.Value.cardinality);

        foreach (KeyValuePair<ListViewItem, TextSection> kvp in sorted)
        {
            TextSection sec = kvp.Value;
            ListViewItem key = kvp.Key;

            textSecs.Remove(key);
            textSecs.Add(key, sec);
        }
    }
于 2008-09-25T00:34:34.753 回答
0

简短的回答是,自从字典“表示键和值的集合”以来,不应该有办法。这并不意味着任何排序。您可能发现的任何 hack 都超出了该类的定义,并且可能会更改。

您可能应该首先问自己在这种情况下是否真的需要字典,或者您是否可以使用 KeyValuePairs 列表。

否则,这样的事情可能会有用:

public class IndexableDictionary<T1, T2> : Dictionary<T1, T2>
{
    private SortedDictionary<int, T1> _sortedKeys;

    public IndexableDictionary()
    {
        _sortedKeys = new SortedDictionary<int, T1>();
    }
    public new void Add(T1 key, T2 value)
    {
        _sortedKeys.Add(_sortedKeys.Count + 1, key);
        base.Add(key, value);
    }

    private IEnumerable<KeyValuePair<T1, T2>> Enumerable()
    {
        foreach (T1 key in _sortedKeys.Values)
        {
            yield return new KeyValuePair<T1, T2>(key, this[key]);
        }
    }

    public new IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
    {
        return Enumerable().GetEnumerator();
    }

    public KeyValuePair<T1, T2> this[int index]
    {
        get
        {
            return new KeyValuePair<T1, T2> (_sortedKeys[index], base[_sortedKeys[index]]);
        }
        set
        {
            _sortedKeys[index] = value.Key;
            base[value.Key] = value.Value;
        }

    }


}

客户端代码看起来像这样:

    static void Main(string[] args)
    {
        IndexableDictionary<string, string> fooDict = new IndexableDictionary<string, string>();

        fooDict.Add("One", "One");
        fooDict.Add("Two", "Two");
        fooDict.Add("Three", "Three");

        // Print One, Two, Three
        foreach (KeyValuePair<string, string> kvp in fooDict)
            Console.WriteLine(kvp.Value);



        KeyValuePair<string, string> temp = fooDict[1];
        fooDict[1] = fooDict[2];
        fooDict[2] = temp;


        // Print Two, One, Three
        foreach (KeyValuePair<string, string> kvp in fooDict)
            Console.WriteLine(kvp.Value);

        Console.ReadLine();
    }

更新:出于某种原因,它不会让我评论我自己的答案。

无论如何,IndexableDictionary 与 OrderedDictionary 的不同之处在于

  1. “OrderedDictionary 的元素不以任何方式排序。” 所以foreach不会关注数字索引
  2. 它是强类型的,所以你不必乱用 DictionaryEntry 结构中的东西
于 2008-09-25T00:40:34.143 回答