更改C#词典中项目的基数
我有字典,像
Dictionary<Foo,String> fooDict
我逐步浏览字典中的所有内容,例如
foreach (Foo foo in fooDict.Keys)
MessageBox.show(fooDict[foo]);
这样做是按照将foos添加到字典的顺序进行的,因此添加的第一项是返回的第一个foo。
如何更改基数,例如,添加的第三个foo将是返回的第二个foo?换句话说,我想更改其"索引"。
解决方案
我没有在该领域受过充分的教育,可以正确回答问题,但是我觉得字典会根据键对值进行排序,以便执行快速键搜索。这表明字典是根据键比较按键值排序的。但是,考虑到对象方法,我认为它们正在使用哈希码来比较不同的对象,因为对键的类型没有要求。这只是一个猜测。知识渊博的人应该填写更多细节。
当字典的目的是为任意类型建立索引时,为什么对操纵字典的"索引"感兴趣?
如果我们阅读了MSDN上的文档,则会看到以下内容:
"物品的退回顺序是不确定的。"
我们不能保证订单的顺序,因为字典不是列表或者数组。这意味着要通过键来查找值,并且任何迭代值的能力都只是一种便利,但是顺序不是我们应该依赖的行为。
我不知道是否有人会觉得这有用,但这就是我最终弄清楚的东西。它似乎可以工作(我的意思是它不会引发任何异常),但是我仍然无法像我希望的那样测试它是否有效。不过,我之前也做过类似的事情。
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);
}
}
简短的答案是,自从字典"代表键和值的集合"以来,应该没有办法。这并不意味着任何排序。我们可能会发现的任何黑客行为都超出了类的定义,并且可能会发生变化。
我们可能首先应该问自己,在这种情况下是否确实需要使用Dictionary,或者是否可以使用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的不同之处在于
- " OrderedDictionary的元素不会以任何方式排序。"所以foreach不会关注数字索引
- 它是强类型的,因此我们不必弄乱从DictionaryEntry结构中强制转换内容
我们可能对System.Collections.Specialized名称空间中的OrderedDicationary类感兴趣。
如果我们在最底端查看评论,则MSFT的某人已发布了此有趣的注释:
This type is actually misnamed; it is not an 'ordered' dictionary as such, but rather an 'indexed' dictionary. Although, today there is no equivalent generic version of this type, if we add one in the future it is likely that we will name such as type 'IndexedDictionary'.
我认为从此类派生并制作OrderedDictionary的通用版本将是微不足道的。

