我正在使用Dictionary<string, int> ,其中int是键的计数。

现在,我需要访问Dictionary中最后插入的Key,但我不知道它的名字。 显而易见的尝试:

int LastCount = mydict[mydict.keys[mydict.keys.Count]];

不起作用,因为Dictionary.Keys没有实现[] -indexer。

我只是想知道是否有类似的类? 我想过使用Stack,但只存储一个字符串。 我现在可以创建自己的结构,然后使用Stack<MyStruct> ,但我想知道是否还有另一种选择,本质上是一个在Keys上实现[] -indexer的Dictionary?

===============>>#1 票数:215 已采纳

正如@Falanwe在评论中指出的那样,做这样的事情是不正确的

int LastCount = mydict.Keys.ElementAt(mydict.Count -1);

不应该依赖于词典中键的顺序。 如果您需要订购,您应该使用OrderedDictionary ,如本答案所示 此页面上的其他答案也很有趣。

===============>>#2 票数:57

您可以使用OrderedDictionary

表示键或索引可访问的键/值对的集合。

===============>>#3 票数:17

字典是一个哈希表,所以你不知道插入的顺序!

如果你想知道最后插入的密钥,我建议扩展Dictionary以包含LastKeyInserted值。

例如:

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

}

您将遇到问题,但是当您使用.Remove() ,为了克服这个问题,您必须保留插入的键的有序列表。

===============>>#4 票数:8

为什么不直接扩展字典类以添加最后一个键插入属性。 可能会出现以下情况?

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);
    }
}

===============>>#5 票数:6

你总是可以这样做:

string[] temp = new string[mydict.count];
mydict.Keys.CopyTo(temp, 0)
int LastCount = mydict[temp[mydict.count - 1]]

但我不推荐它。 无法保证最后插入的密钥位于数组的末尾。 MSDN上的密钥的排序未指定,可能会更改。 在我非常简短的测试中,它看起来似乎是按照插入的顺序,但你最好建立像堆栈一样的正确簿记 - 正如你的建议(尽管我没有看到基于你的结构的需要)其他语句) - 或单变量缓存,如果您只需要知道最新的密钥。

===============>>#6 票数:5

我认为你可以做这样的事情,语法可能是错的,暂时没有使用C#来获取最后一项

Dictionary<string, int>.KeyCollection keys = mydict.keys;
string lastKey = keys.Last();

或使用Max而不是Last来获取最大值,我不知道哪一个更适合您的代码。

===============>>#7 票数:4

如果您决定使用可能破损的危险代码,此扩展函数将根据其内部索引从Dictionary<K,V>获取密钥(对于Mono和.NET,其目前看起来与你可以通过枚举Keys属性获得)。

最好使用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);
    }
};

===============>>#8 票数:4

我同意帕特里克回答的第二部分。 即使在某些测试中它似乎保持插入顺序,文档(以及字典和散列的正常行为)明确指出排序未指定。

根据按键的顺序,你只是要求麻烦。 添加你自己的簿记(正如帕特里克所说,只是最后一个添加键的一个变量),以确保。 另外,不要被字典中的Last和Max等所有方法所诱惑,因为这些方法可能与关键比较器有关(我不确定)。

===============>>#9 票数:4

如果密钥嵌入在值中,则一种替代方案是KeyedCollection

只需在密封类中创建一个基本实现即可使用。

所以要替换Dictionary<string, int> (这不是一个很好的例子,因为没有明确的int键)。

private sealed class IntDictionary : KeyedCollection<string, int>
{
    protected override string GetKeyForItem(int item)
    {
        // The example works better when the value contains the key. It falls down a bit for a dictionary of ints.
        return item.ToString();
    }
}

KeyedCollection<string, int> intCollection = new ClassThatContainsSealedImplementation.IntDictionary();

intCollection.Add(7);

int valueByIndex = intCollection[0];

===============>>#10 票数:3

你提出这个问题的方式让我相信字典中的int包含了字典中项目的“位置”。 判断密钥没有按照添加的顺序存储,如果这是正确的,那就意味着keys.Count(或.Count - 1,如果你使用从零开始)仍应该始终是最后输入的密钥的编号?

如果这是正确的,是否有任何理由你不能使用Dictionary <int,string>以便你可以使用mydict [mydict.Keys.Count]?

===============>>#11 票数:2

您还可以使用SortedList及其Generic对应项。 这两个类和安德鲁·彼得斯回答提到的OrderedDictionary是字典类,其中的项目可以通过索引(位置)和键来访问。 如何使用这些类,你可以找到: SortedList ClassSortedList Generic Class

===============>>#12 票数:2

使用索引作为参考字典可能不是很直观,但是,您可以使用KeyValuePair数组进行类似的操作:

恩。 KeyValuePair<string, string>[] filters;

===============>>#13 票数:2

我不知道这是否可行,因为我非常确定密钥没有按照添加的顺序存储,但您可以将KeysCollection转换为List,然后获取列表中的最后一个密钥...但值得一看。

我能想到的唯一另一件事就是将密钥存储在查找列表中,并在将密钥添加到字典之前将密钥添加到列表中......这不是很好。

===============>>#14 票数:2

要扩展Daniels帖子以及他对密钥的评论,因为无论如何密钥都嵌入在值中,您可以使用KeyValuePair<TKey, TValue>作为值。 对此的主要原因是,通常,密钥不一定直接从值中导出。

然后它看起来像这样:

public sealed class CustomDictionary<TKey, TValue>
  : KeyedCollection<TKey, KeyValuePair<TKey, TValue>>
{
  protected override TKey GetKeyForItem(KeyValuePair<TKey, TValue> item)
  {
    return item.Key;
  }
}

要像上一个示例中那样使用它,您需要:

CustomDictionary<string, int> custDict = new CustomDictionary<string, int>();

custDict.Add(new KeyValuePair<string, int>("key", 7));

int valueByIndex = custDict[0].Value;
int valueByKey = custDict["key"].Value;
string keyByIndex = custDict[0].Key;

===============>>#15 票数:1

Visual Studio的UserVoice提供了dotmore对通用OrderedDictionary实现的链接。

但是,如果您只需按索引获取键/值对,而不需要按键获取值,则可以使用一个简单的技巧。 声明一些泛型类(我称之为ListArray)如下:

class ListArray<T> : List<T[]> { }

您也可以使用构造函数声明它:

class ListArray<T> : List<T[]>
{
    public ListArray() : base() { }
    public ListArray(int capacity) : base(capacity) { }
}

例如,您从文件中读取了一些键/值对,只是想按照它们的读取顺序存储它们,以便稍后通过索引获取它们:

ListArray<string> settingsRead = new ListArray<string>();
using (var sr = new StreamReader(myFile))
{
    string line;
    while ((line = sr.ReadLine()) != null)
    {
        string[] keyValueStrings = line.Split(separator);
        for (int i = 0; i < keyValueStrings.Length; i++)
            keyValueStrings[i] = keyValueStrings[i].Trim();
        settingsRead.Add(keyValueStrings);
    }
}
// Later you get your key/value strings simply by index
string[] myKeyValueStrings = settingsRead[index];

您可能已经注意到,您可能不一定只是ListArray中的键/值对。 项目数组可以是任何长度,如锯齿状数组。

  ask by Michael Stum translate from so

未解决问题?本站智能推荐: