web-dev-qa-db-ja.com

値に基づいてC#辞書のキー/値ペアのインデックスを取得します

特定の値のインデックスを取得するプロパティまたはメソッドが存在するかどうかを知りたいです。

辞書には、渡された値が存在する場合にtrueを返すContains()メソッドがあるため、このメソッドはほとんど必要なものを実装しています。

私はすべての値のペアをループして条件をチェックできることを知っていますが、おそらくこれを行うための最適化された方法があるので、私は尋ねます。

34
mjsr

辞書内に「インデックス」という概念はありません-基本的に順序付けられていません。もちろん、繰り返し処理を行うと、項目はsomeの順序で取得されますが、その順序は保証されておらず、時間とともに変化する可能性があります(特にエントリを追加または削除する場合)。

明らかにKeyValuePairプロパティを使用するだけでKeyからキーを取得できるため、辞書のインデクサーを使用できます。

var pair = ...;
var value = dictionary[pair.Key];
Assert.AreEqual(value, pair.Value);

あなたは本当にあなたがやろうとしていることを言っていません。特定の値に対応するキーを見つけようとしている場合は、次を使用できます。

var key = dictionary.Where(pair => pair.Value == desiredValue)
                    .Select(pair => pair.Key)
                    .FirstOrDefault();

エントリが存在しない場合、keyはnullになります。

これは、キー型が参照型であると仮定しています...値型である場合、少し異なる方法で処理する必要があります。

もちろん、実際にキーで値を検索したい場合は、既存の辞書に加えて逆方向にマップする別の辞書の使用を検討する必要があります。

30
Jon Skeet

FooDictionaryという辞書があるとします

fooDictionary.Values.ToList().IndexOf(someValue);

Values.ToList()は、辞書の値をsomeValueオブジェクトのリストに変換します。

IndexOf(someValue)は、問題のsomeValueオブジェクトを探して新しいリストを検索し、ディクショナリ内のキー/値ペアのインデックスに一致するインデックスを返します。

このメソッドは辞書キーを気にしません。探している値のインデックスを単に返します。

ただし、これは、いくつかの一致する「someValue」オブジェクトが存在する可能性があるという問題を考慮していません。

24
EricM

System.Collections.Specialized.OrderedDictionary 、ただし一般的ではないか、独自に実装します( example )。

OrderedDictionaryIndexOfをサポートしていませんが、実装は簡単です:

public static class OrderedDictionaryExtensions
{
    public static int IndexOf(this OrderedDictionary dictionary, object value)
    {
        for(int i = 0; i < dictionary.Count; ++i)
        {
            if(dictionary[i] == value) return i;
        }
        return -1;
    }
}
9
max

これを支援するためにLINQを使用できます。

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "hi");
dict.Add(2, "NotHi");
dict.Add(3, "Bah");

var item = (from d in dict
            where d.Value == "hi"
            select d.Key).FirstOrDefault();

Console.WriteLine(item); //Prints 1
2
George Stocker
辞書のキー/値によってインデックスを検索できます
Dictionary<string, string> myDictionary = new Dictionary<string, string>();
myDictionary.Add("a", "x");
myDictionary.Add("b", "y");
int i = Array.IndexOf(myDictionary.Keys.ToArray(), "a");
int j = Array.IndexOf(myDictionary.Values.ToArray(), "y");
2
malik

値を検索する場合、-すべてのデータをループする必要があります。ただし、関与するコードを最小限に抑えるには、LINQを使用できます。

例:

以下のように定義された辞書:

Dictionary<Int32, String> dict;

次のコードを使用できます。

// Search for all keys with given value
Int32[] keys = dict.Where(kvp => kvp.Value.Equals("SomeValue")).Select(kvp => kvp.Key).ToArray();

// Search for first key with given value
Int32 key = dict.First(kvp => kvp.Value.Equals("SomeValue")).Key;
1
decyclone

no、ディクショナリに同様のIndexOfはありませんが、ContainsKeyメソッドを使用して、キーがディクショナリに属する​​かどうかを取得できます

0
TalentTuner

maxanswer へのコメントでは、本当に取得したいのはkey特定の値を含むKeyValuePairのではなく、インデックスではありません。質問を編集して、より明確にすることができます。

指摘する価値があります( EricM 彼の answer でこれに触れた)値がに複数回現れる可能性がある辞書。この場合、どのキーを取得するかを考える必要があります。たとえば、最初に現れるもの、最後に来るもの、それらすべて?

各キーに一意の値があることが確実な場合、最初のキーの値がキーとして機能し、前のキーの値が値として機能する別の辞書を使用できます。そうしないと、この2番目の辞書のアイデア( suggested by Jon Skeet )は機能しません。すべての可能なキーのどれを新しい値として使用するかを再度考えなければならないからです。辞書。

インデックスについて尋ねた場合、しかし、EricMの答えは大丈夫でしょう。次に、以下を使用して、問題のKeyValuePairを取得できます。

yourDictionary.ElementAt(theIndexYouFound);

提供されたyourDictionaryで物事を追加/削除しないこと。

PS:もうほぼ7年が経ちましたが、一体何なのでしょう。私はOPに対処するために私の答えを定式化するのが最善だと思ったが、もちろん今ではそれは他のほぼすべての人butOPに対する答えであると言うことができる。それを完全に知って、ありがとう。

0
zerzevul