166

Dictionary<string, int>キーの数である aを使用してintいます。

ここで、辞書内の最後に挿入されたキーにアクセスする必要がありますが、その名前がわかりません。明らかな試み:

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

Dictionary.Keys[]-インデクサーを実装していないため、機能しません。

似たようなクラスがあるのだろうか?スタックを使用することを考えましたが、それは文字列のみを格納します。独自の構造体を作成して を使用できるようStack<MyStruct>になりましたが、キーに []-indexer を実装する基本的にディクショナリである別の代替手段があるのだろうか?

4

15 に答える 15

231

@Falanwe がコメントで指摘しているように、次のようなことを行うのは正しくありません。

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

Dictionary のキーの順序に依存しないでください。注文が必要な場合は、この回答で提案されているように、 OrderedDictionaryを使用する必要があります。このページの他の回答も興味深いものです。

于 2011-01-19T13:21:27.887 に答える
59

OrderedDictionaryを使用できます。

キーまたはインデックスからアクセスできるキーと値のペアのコレクションを表します。

于 2008-08-08T01:23:22.887 に答える
18

Dictionary はハッシュ テーブルであるため、挿入の順序はわかりません。

最後に挿入されたキーを知りたい場合は、 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()これを克服するためにこれを使用すると、挿入されたキーの順序付きリストを保持する必要があります。

于 2009-04-16T14:09:29.563 に答える
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);
    }
}
于 2008-08-07T11:15:35.093 に答える
6

あなたはいつでもこれを行うことができます:

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

しかし、私はそれをお勧めしません。最後に挿入されたキーが配列の最後にあるという保証はありません。MSDNでのキーの順序は指定されておらず、変更される可能性があります。私の非常に簡単なテストでは、挿入順になっているように見えますが、スタックのように適切な簿記を作成する方がよいでしょう。他のステートメント)-または、最新のキーを知る必要がある場合は、単一の変数キャッシュ。

于 2008-08-07T01:13:22.377 に答える
5

私はあなたがこのようなことをすることができると思います、構文が間違っているかもしれません、しばらくの間C#を使用していません最後のアイテムを取得するために

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

または、Lastの代わりにMaxを使用して最大値を取得しますが、どちらがコードに適しているかわかりません。

于 2008-08-07T01:18:25.657 に答える
4

キーが値に埋め込まれている場合、1つの代替手段は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];
于 2011-07-20T00:45:48.053 に答える
4

破損しやすい危険なコードを使用することにした場合、この拡張関数は、内部インデックスに従って からキーを取得します(Mono および .NET の場合、現在、プロパティDictionary<K,V>を列挙して取得する順序と同じように見えます)。 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);
    }
};
于 2010-04-12T04:44:58.903 に答える
4

パトリックの答えの2番目の部分に同意します。一部のテストでは挿入順序が維持されているように見えても、ドキュメント (および辞書とハッシュの通常の動作) では、順序が未指定であると明示的に述べられています。

キーの順序によっては、トラブルを求めているだけです。確実にするために、独自の簿記を追加してください(Patrickが言ったように、最後に追加されたキーの変数は1つだけです)。また、おそらくキーコンパレーターに関連しているため、辞書の Last や Max などのすべてのメソッドに誘惑されないでください (それについてはわかりません)。

于 2008-08-07T02:38:29.163 に答える
3

質問の言い方から、辞書の int には辞書上のアイテムの「位置」が含まれていると私は信じています。キーが追加された順序で格納されていないというアサーションから判断すると、これが正しい場合、keys.Count (ゼロベースを使用している場合は .Count - 1) が引き続き必要であることを意味します常に最後に入力されたキーの番号になりますか?

それが正しい場合、代わりに Dictionary<int, string> を使用して mydict[ mydict.Keys.Count ] を使用できない理由はありますか?

于 2008-08-07T02:40:52.747 に答える
2

キーが追加された順序で保存されていないことは確かなので、これが機能するかどうかはわかりませんが、KeysCollectionをリストにキャストして、リストの最後のキーを取得することはできます...しかし、一見の価値があります。

私が考えることができる他の唯一のことは、キーをルックアップリストに保存し、辞書に追加する前にリストにキーを追加することです...それはかなりではありません。

于 2008-08-07T01:15:55.350 に答える
2

ダニエルズの投稿とキーに関する彼のコメントを拡張するには、キーはとにかく値に埋め込まれているKeyValuePair<TKey, TValue>ため、値としてaを使用することに頼ることができます。これの主な理由は、一般に、キーが必ずしも値から直接導出できるとは限らないということです。

次に、次のようになります。

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;
于 2011-07-20T09:21:45.130 に答える
2

ディクショナリは参照用のインデックスを使用するのにあまり直感的ではないかもしれませんが、KeyValuePairの配列で同様の操作を行うことができます:

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

于 2016-04-06T21:15:54.217 に答える
2

SortedList とそのジェネリック版も使用できます。これらの 2 つのクラスと、Andrew Peters の回答で言及されている OrderedDictionary は、インデックス (位置) とキーによってアイテムにアクセスできる辞書クラスです。これらのクラスの使用方法: SortedList ClassSortedList Generic Class

于 2015-03-25T18:13:00.467 に答える
1

Visual Studio のUserVoiceは、dotmore による汎用 OrderedDictionary 実装へのリンクを提供します。

ただし、キーと値のペアをインデックスで取得するだけで、キーで値を取得する必要がない場合は、1 つの簡単なトリックを使用できます。次のように、いくつかのジェネリック クラス (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 には必ずしもキーと値のペアだけを含めることができるわけではありません。アイテム配列は、ジャグ配列のように任意の長さにすることができます。

于 2016-11-03T08:42:21.953 に答える