.NET 基本クラス ライブラリに重複キーの使用を許可する辞書クラスはありますか? 私が見つけた唯一の解決策は、たとえば次のようなクラスを作成することです。
Dictionary<string, List<object>>
しかし、これは実際に使用するのはかなりイライラします。Java では、MultiMap がこれを達成すると信じていますが、.NET では類似物を見つけることができません。
.NET 基本クラス ライブラリに重複キーの使用を許可する辞書クラスはありますか? 私が見つけた唯一の解決策は、たとえば次のようなクラスを作成することです。
Dictionary<string, List<object>>
しかし、これは実際に使用するのはかなりイライラします。Java では、MultiMap がこれを達成すると信じていますが、.NET では類似物を見つけることができません。
.NET 3.5 を使用している場合は、Lookup
クラスを使用します。
編集: 通常、Lookup
using を作成しEnumerable.ToLookup
ます。これは、後で変更する必要がないことを前提としていますが、通常はそれで十分です。
それがうまくいかない場合は、フレームワークに役立つものは何もないと思います-そして、辞書を使用するのは最高です:(
List クラスは、コレクションを反復処理したい重複を含むキー/値コレクションに対して実際に非常にうまく機能します。例:
List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
// add some values to the collection here
for (int i = 0; i < list.Count; i++)
{
Print(list[i].Key, list[i].Value);
}
List< KeyValuePair< string, string > > を使用してこれを行う 1 つの方法を次に示します。
public class ListWithDuplicates : List<KeyValuePair<string, string>>
{
public void Add(string key, string value)
{
var element = new KeyValuePair<string, string>(key, value);
this.Add(element);
}
}
var list = new ListWithDuplicates();
list.Add("k1", "v1");
list.Add("k1", "v2");
list.Add("k1", "v3");
foreach(var item in list)
{
string x = string.format("{0}={1}, ", item.Key, item.Value);
}
出力 k1=v1、k1=v2、k1=v3
キーと値の両方として文字列を使用している場合は、System.Collections.Specialized.NameValueCollectionを使用できます。これは、GetValues(string key) メソッドを介して文字列値の配列を返します。
とりわけ、MultiDictionary というクラスを含むPowerCollectionsライブラリに出くわしました。これにより、このタイプの機能がきちんとラップされます。
ルックアップの使用に関する非常に重要な注意事項:
を実装するオブジェクトをLookup(TKey, TElement)
呼び出すことで、 のインスタンスを作成できます。ToLookup
IEnumerable(T)
の新しいインスタンスを作成するパブリック コンストラクターはありませんLookup(TKey, TElement)
。さらに、Lookup(TKey, TElement)
オブジェクトは不変です。つまり、オブジェクトの作成後に要素やキーを追加したり、オブジェクトから削除したりすることはできませんLookup(TKey, TElement)
。
これは、ほとんどの用途でショーストッパーになると思います。
私は何かList<KeyValuePair<object, object>>
が仕事をするだろうと思います。
>= .NET 4 を使用している場合は、Tuple
クラスを使用できます。
// declaration
var list = new List<Tuple<string, List<object>>>();
// to add an item to the list
var item = Tuple<string, List<object>>("key", new List<object>);
list.Add(item);
// to iterate
foreach(var i in list)
{
Console.WriteLine(i.Item1.ToString());
}
元の質問への回答。TheDictionary<string, List<object>>
と呼ばれるクラスに実装されているようなものです。MultiMap
Code Project
以下のリンクで詳細を確認できます: http://www.codeproject.com/KB/cs/MultiKeyDictionary.aspx
このList<KeyValuePair<string, object>>
オプションを使用すると、LINQ を使用して検索を実行できます。
List<KeyValuePair<string, object>> myList = new List<KeyValuePair<string, object>>();
//fill it here
var q = from a in myList Where a.Key.Equals("somevalue") Select a.Value
if(q.Count() > 0){ //you've got your value }
NameValueCollection は、1 つのキー (文字列でもあります) の下で複数の文字列値をサポートしますが、これは私が認識している唯一の例です。
そのような機能が必要な状況に遭遇したとき、私はあなたの例に似た構造を作成する傾向があります。
私の使い方はただ
Dictionary<string, List<string>>
このようにして、文字列のリストを保持する単一のキーがあります。
例:
List<string> value = new List<string>();
if (dictionary.Contains(key)) {
value = dictionary[key];
}
value.Add(newValue);
実際の重複ではなく、合同ということですか?そうしないと、ハッシュテーブルは機能しません。
合同とは、2 つの別個のキーが同等の値にハッシュできることを意味しますが、キーは等しくありません。
例: ハッシュテーブルのハッシュ関数が単に hashval = key mod 3 だったとします。1 と 4 の両方が 1 にマップされますが、値は異なります。ここで、リストのアイデアが役立ちます。
1 を検索する必要がある場合、その値は 1 にハッシュされ、Key = 1 が見つかるまでリストが走査されます。
重複するキーの挿入を許可すると、どのキーがどの値にマップされるかを区別できなくなります。
同じ答えを探してこの投稿に出くわしましたが、何も見つからなかったので、辞書のリストを使用して必要最小限のソリューション例を作成し、 [] 演算子をオーバーライドして、他のすべての辞書が新しい辞書を持っているときにリストに新しい辞書を追加しました。指定されたキー (set) を取得し、値のリストを返します (get)。
それは醜くて非効率的で、キーでのみ取得/設定し、常にリストを返しますが、機能します:
class DKD {
List<Dictionary<string, string>> dictionaries;
public DKD(){
dictionaries = new List<Dictionary<string, string>>();}
public object this[string key]{
get{
string temp;
List<string> valueList = new List<string>();
for (int i = 0; i < dictionaries.Count; i++){
dictionaries[i].TryGetValue(key, out temp);
if (temp == key){
valueList.Add(temp);}}
return valueList;}
set{
for (int i = 0; i < dictionaries.Count; i++){
if (dictionaries[i].ContainsKey(key)){
continue;}
else{
dictionaries[i].Add(key,(string) value);
return;}}
dictionaries.Add(new Dictionary<string, string>());
dictionaries.Last()[key] =(string)value;
}
}
}
U は、辞書を使用したい場所ごとに複合文字列キーを作成する方法を定義できます。たとえば、この方法を使用してキーを作成する必要があります。
private string keyBuilder(int key1, int key2)
{
return string.Format("{0}/{1}", key1, key2);
}
使用するため:
myDict.ContainsKey(keyBuilder(key1, key2))
重複キーは、ディクショナリの契約全体を破ります。ディクショナリでは、各キーは一意であり、単一の値にマップされます。オブジェクトを任意の数の追加オブジェクトにリンクしたい場合、最善の策は DataSet (一般的にはテーブル) に似たものかもしれません。キーを 1 つの列に入れ、値をもう 1 つの列に入れます。これはディクショナリよりも大幅に遅くなりますが、それはキー オブジェクトをハッシュする機能を失うこととのトレードオフです。
これも可能です:
Dictionary<string, string[]> previousAnswers = null;
このようにして、一意のキーを持つことができます。これがうまくいくことを願っています。