C# 通过数字索引访问 Dictionary.Keys 键
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing a Dictionary.Keys Key through a numeric index
提问by Michael Stum
I'm using a Dictionary<string, int>
where the int
is a count of the key.
我正在使用一个Dictionary<string, int>
whereint
是键的计数。
Now, I need to access the last-inserted Key inside the Dictionary, but I do not know the name of it. The obvious attempt:
现在,我需要访问 Dictionary 中最后插入的 Key,但我不知道它的名称。明显的尝试:
int LastCount = mydict[mydict.keys[mydict.keys.Count]];
does not work, because Dictionary.Keys
does not implement a []-indexer.
不起作用,因为Dictionary.Keys
没有实现 []-indexer。
I just wonder if there is any similar class? I thought about using a Stack, but that only stores a string. I could now create my own struct and then use a Stack<MyStruct>
, but I wonder if there is another alternative, essentially a Dictionary that implements an []-indexer on the Keys?
我只是想知道是否有类似的课程?我想过使用堆栈,但它只存储一个字符串。我现在可以创建我自己的结构然后使用 a Stack<MyStruct>
,但我想知道是否还有另一种选择,本质上是一个在键上实现 []-indexer 的字典?
采纳答案by Vitor Hugo
As @Falanwe points out in a comment, doing something like this is incorrect:
正如@Falanwe 在评论中指出的那样,做这样的事情是不正确的:
int LastCount = mydict.Keys.ElementAt(mydict.Count -1);
You should notdepend on the order of keys in a Dictionary. If you need ordering, you should use an OrderedDictionary, as suggested in this answer. The other answers on this page are interesting as well.
您不应该依赖字典中键的顺序。如果您需要订购,您应该使用OrderedDictionary,如本答案中所建议。此页面上的其他答案也很有趣。
回答by Patrick
You could always do this:
你总是可以这样做:
string[] temp = new string[mydict.count];
mydict.Keys.CopyTo(temp, 0)
int LastCount = mydict[temp[mydict.count - 1]]
But I wouldn't recommend it. There's no guarantee that the last inserted key will be at the end of the array. The ordering for Keys on MSDNis unspecified, and subject to change. In my very brief test, it does seem to be in order of insertion, but you'd be better off building in proper bookkeeping like a stack--as you suggest (though I don't see the need of a struct based on your other statements)--or single variable cache if you just need to know the latest key.
但我不会推荐它。不能保证最后插入的键位于数组的末尾。MSDN上的密钥排序未指定,可能会发生变化。在我非常简短的测试中,它似乎是按插入顺序排列的,但是您最好像堆栈一样构建适当的簿记 - 正如您所建议的(尽管我不认为需要基于您的结构其他语句)--或单个变量缓存,如果您只需要知道最新的密钥。
回答by lomaxx
I don't know if this would work because I'm pretty sure that the keys aren't stored in the order they are added, but you could cast the KeysCollection to a List and then get the last key in the list... but it would be worth having a look.
我不知道这是否可行,因为我很确定键不是按照添加顺序存储的,但是您可以将 KeysCollection 转换为列表,然后获取列表中的最后一个键...但值得一看。
The only other thing I can think of is to store the keys in a lookup list and add the keys to the list before you add them to the dictionary... it's not pretty tho.
我能想到的唯一另一件事是将键存储在查找列表中并将键添加到列表中,然后再将它们添加到字典中……这不太好。
回答by Juan
I think you can do something like this, the syntax might be wrong, havent used C# in a while To get the last item
我觉得你可以这样做,可能是语法不对,有段时间没用C#来搞定最后一项了
Dictionary<string, int>.KeyCollection keys = mydict.keys;
string lastKey = keys.Last();
or use Max instead of Last to get the max value, I dont know which one fits your code better.
或者使用 Max 而不是 Last 来获取最大值,我不知道哪个更适合您的代码。
回答by Stephen Pellicer
I agree with the second part of Patrick's answer. Even if in some tests it seems to keep insertion order, the documentation (and normal behavior for dictionaries and hashes) explicitly states the ordering is unspecified.
我同意帕特里克回答的第二部分。即使在某些测试中它似乎保持插入顺序,文档(以及字典和哈希的正常行为)明确指出排序是未指定的。
You're just asking for trouble depending on the ordering of the keys. Add your own bookkeeping (as Patrick said, just a single variable for the last added key) to be sure. Also, don't be tempted by all the methods such as Last and Max on the dictionary as those are probably in relation to the key comparator (I'm not sure about that).
您只是根据键的顺序自找麻烦。添加您自己的簿记(正如帕特里克所说,最后添加的键只是一个变量)以确保。另外,不要被字典中的 Last 和 Max 等所有方法所吸引,因为这些方法可能与键比较器有关(我不确定)。
回答by Jeremy Privett
The way you worded the question leads me to believe that the int in the Dictionary contains the item's "position" on the Dictionary. Judging from the assertion that the keys aren't stored in the order that they're added, if this is correct, that would mean that keys.Count (or .Count - 1, if you're using zero-based) should still always be the number of the last-entered key?
您提出问题的方式使我相信字典中的 int 包含该项目在字典中的“位置”。从键不是按添加顺序存储的断言来看,如果这是正确的,那将意味着 keys.Count(或 .Count - 1,如果您使用的是基于零的)应该仍然始终是最后输入的密钥的编号?
If that's correct, is there any reason you can't instead use Dictionary<int, string> so that you can use mydict[ mydict.Keys.Count ]?
如果这是正确的,是否有任何理由不能改为使用 Dictionary<int, string> 以便可以使用 mydict[ mydict.Keys.Count ]?
回答by Calanus
Why don't you just extend the dictionary class to add in a last key inserted property. Something like the following maybe?
为什么不扩展字典类以添加最后一个键插入的属性。像下面这样的东西?
public class ExtendedDictionary : Dictionary<string, int>
{
private int lastKeyInserted = -1;
public int LastKeyInserted
{
get { return lastKeyInserted; }
set { lastKeyInserted = value; }
}
public void AddNew(string s, int i)
{
lastKeyInserted = i;
base.Add(s, i);
}
}
回答by Andrew Peters
You can use an OrderedDictionary.
您可以使用OrderedDictionary。
Represents a collection of key/value pairs that are accessible by the key or index.
表示可通过键或索引访问的键/值对的集合。
回答by Andrew Peters
A Dictionary is a Hash Table, so you have no idea the order of insertion!
字典是一个哈希表,所以你不知道插入的顺序!
If you want to know the last inserted key I would suggest extending the Dictionary to include a LastKeyInserted value.
如果您想知道最后插入的键,我建议扩展 Dictionary 以包含 LastKeyInserted 值。
E.g.:
例如:
public MyDictionary<K, T> : IDictionary<K, T>
{
private IDictionary<K, T> _InnerDictionary;
public K LastInsertedKey { get; set; }
public MyDictionary()
{
_InnerDictionary = new Dictionary<K, T>();
}
#region Implementation of IDictionary
public void Add(KeyValuePair<K, T> item)
{
_InnerDictionary.Add(item);
LastInsertedKey = item.Key;
}
public void Add(K key, T value)
{
_InnerDictionary.Add(key, value);
LastInsertedKey = key;
}
.... rest of IDictionary methods
#endregion
}
You will run into problems however when you use .Remove()
so to overcome this you will have to keep an ordered list of the keys inserted.
您会遇到问题,但是当您使用.Remove()
so 来克服这个问题时,您必须保留插入的键的有序列表。
回答by Glenn Slayden
In case you decide to use dangerous code that is subject to breakage, this extension function will fetch a key from a Dictionary<K,V>
according to its internal indexing (which for Mono and .NET currently appears to be in the same order as you get by enumerating the Keys
property).
如果您决定使用易被破坏的危险代码,此扩展函数将Dictionary<K,V>
根据其内部索引从 a 中获取一个键(对于 Mono 和 .NET,目前看起来与您通过枚举Keys
属性获得的顺序相同)。
It is much preferable to use Linq: dict.Keys.ElementAt(i)
, but that function will iterate O(N); the following is O(1) but with a reflection performance penalty.
最好使用 Linq: dict.Keys.ElementAt(i)
,但该函数将迭代 O(N); 以下是 O(1) 但具有反射性能损失。
using System;
using System.Collections.Generic;
using System.Reflection;
public static class Extensions
{
public static TKey KeyByIndex<TKey,TValue>(this Dictionary<TKey, TValue> dict, int idx)
{
Type type = typeof(Dictionary<TKey, TValue>);
FieldInfo info = type.GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance);
if (info != null)
{
// .NET
Object element = ((Array)info.GetValue(dict)).GetValue(idx);
return (TKey)element.GetType().GetField("key", BindingFlags.Public | BindingFlags.Instance).GetValue(element);
}
// Mono:
info = type.GetField("keySlots", BindingFlags.NonPublic | BindingFlags.Instance);
return (TKey)((Array)info.GetValue(dict)).GetValue(idx);
}
};