質問
ある辞書クラス。NETベースクラスライブラリを複製キーは何に使われるのでしょうか。の唯一のソリューションをしますが、たとえば、クラスのように:
Dictionary<string, List<object>>
これはなかなか直ちに医師の診断を受けることを実際に利用します。Javaでは、いると思いMultiMap達成すものを見つけることができなアナログです。います。
解決
.NET 3.5を使用している場合は、 Lookup
クラス。
編集:通常は、を使用して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 <!> ltで行う方法の1つです。 KeyValuePair <!> lt;文字列、文字列<!> gt; <!> gt;
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)メソッドを介して文字列値の配列を返します。
PowerCollections ライブラリに出会いました。このライブラリには、とりわけ、MultiDictionaryと呼ばれるクラスが含まれています。これにより、このタイプの機能がきちんとラップされます。
ルックアップの使用に関する非常に重要な注意事項:
Lookup(TKey, TElement)
を実装するオブジェクトでToLookup
を呼び出すことにより、IEnumerable(T)
のインスタンスを作成できます
<=>の新しいインスタンスを作成するパブリックコンストラクターはありません。さらに、<=>オブジェクトは不変です。つまり、<=>オブジェクトの作成後は、要素またはキーを追加または削除できません。
これは、ほとんどの用途のショーストッパーになると思います。
List<KeyValuePair<object, object>>
のようなものがジョブを実行すると思います。
<!> gt; = .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());
}
<!> quot;独自のロール<!> quot; <!> quot;重複キー<!> quotを許可する辞書のバージョン。エントリ。大まかな簡単な実装を次に示します。 IDictionary<T>
で基本的にほとんど(すべてではないにしても)のサポートを追加することを検討できます。
public class MultiMap<TKey,TValue>
{
private readonly Dictionary<TKey,IList<TValue>> storage;
public MultiMap()
{
storage = new Dictionary<TKey,IList<TValue>>();
}
public void Add(TKey key, TValue value)
{
if (!storage.ContainsKey(key)) storage.Add(key, new List<TValue>());
storage[key].Add(value);
}
public IEnumerable<TKey> Keys
{
get { return storage.Keys; }
}
public bool ContainsKey(TKey key)
{
return storage.ContainsKey(key);
}
public IList<TValue> this[TKey key]
{
get
{
if (!storage.ContainsKey(key))
throw new KeyNotFoundException(
string.Format(
"The given key {0} was not found in the collection.", key));
return storage[key];
}
}
}
使用方法の簡単な例:
const string key = "supported_encodings";
var map = new MultiMap<string,Encoding>();
map.Add(key, Encoding.ASCII);
map.Add(key, Encoding.UTF8);
map.Add(key, Encoding.Unicode);
foreach (var existingKey in map.Keys)
{
var values = map[existingKey];
Console.WriteLine(string.Join(",", values));
}
元の質問への回答。 Dictionary<string, List<object>>
のようなものは、MultiMap
のCode Project
というクラスに実装されています。
以下のリンクに詳細情報があります: http://www.codeproject.com/KB/cs/MultiKeyDictionary.aspx
NameValueCollectionは、1つのキー(文字列でもある)の下で複数の文字列値をサポートしていますが、私が知っている唯一の例です。
この種の機能が必要な状況に遭遇したとき、あなたの例のような構造を作成する傾向があります。
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 }
私が使う方法はただ
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にハッシュされ、キー= 1が見つかるまでリストが走査されます。
重複キーの挿入を許可した場合、どのキーがどの値にマッピングされるかを区別することはできません。
私がここにポストに答えを見ないrigged、植物庭園、ボージョワーの例のソリューションのリスト辞書をオーバーの[]オペレーターを追加する新たな辞書のリストがすべての出会いを大切に社員全員指定されたキーの設定)、戻り値のリスト(車).
その醜悪でみ込み/セキーで常にリストを返しますが、その作品:
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;
}
}
}
@Hector Correaの回答を汎用型の拡張に変更し、カスタムTryGetValueを追加しました。
public static class ListWithDuplicateExtensions
{
public static void Add<TKey, TValue>(this List<KeyValuePair<TKey, TValue>> collection, TKey key, TValue value)
{
var element = new KeyValuePair<TKey, TValue>(key, value);
collection.Add(element);
}
public static int TryGetValue<TKey, TValue>(this List<KeyValuePair<TKey, TValue>> collection, TKey key, out IEnumerable<TValue> values)
{
values = collection.Where(pair => pair.Key.Equals(key)).Select(pair => pair.Value);
return values.Count();
}
}
これは、2つの方法の並行辞書です。これはあなたに役立つと思います:
public class HashMapDictionary<T1, T2> : System.Collections.IEnumerable
{
private System.Collections.Concurrent.ConcurrentDictionary<T1, List<T2>> _keyValue = new System.Collections.Concurrent.ConcurrentDictionary<T1, List<T2>>();
private System.Collections.Concurrent.ConcurrentDictionary<T2, List<T1>> _valueKey = new System.Collections.Concurrent.ConcurrentDictionary<T2, List<T1>>();
public ICollection<T1> Keys
{
get
{
return _keyValue.Keys;
}
}
public ICollection<T2> Values
{
get
{
return _valueKey.Keys;
}
}
public int Count
{
get
{
return _keyValue.Count;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public List<T2> this[T1 index]
{
get { return _keyValue[index]; }
set { _keyValue[index] = value; }
}
public List<T1> this[T2 index]
{
get { return _valueKey[index]; }
set { _valueKey[index] = value; }
}
public void Add(T1 key, T2 value)
{
lock (this)
{
if (!_keyValue.TryGetValue(key, out List<T2> result))
_keyValue.TryAdd(key, new List<T2>() { value });
else if (!result.Contains(value))
result.Add(value);
if (!_valueKey.TryGetValue(value, out List<T1> result2))
_valueKey.TryAdd(value, new List<T1>() { key });
else if (!result2.Contains(key))
result2.Add(key);
}
}
public bool TryGetValues(T1 key, out List<T2> value)
{
return _keyValue.TryGetValue(key, out value);
}
public bool TryGetKeys(T2 value, out List<T1> key)
{
return _valueKey.TryGetValue(value, out key);
}
public bool ContainsKey(T1 key)
{
return _keyValue.ContainsKey(key);
}
public bool ContainsValue(T2 value)
{
return _valueKey.ContainsKey(value);
}
public void Remove(T1 key)
{
lock (this)
{
if (_keyValue.TryRemove(key, out List<T2> values))
{
foreach (var item in values)
{
var remove2 = _valueKey.TryRemove(item, out List<T1> keys);
}
}
}
}
public void Remove(T2 value)
{
lock (this)
{
if (_valueKey.TryRemove(value, out List<T1> keys))
{
foreach (var item in keys)
{
var remove2 = _keyValue.TryRemove(item, out List<T2> values);
}
}
}
}
public void Clear()
{
_keyValue.Clear();
_valueKey.Clear();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _keyValue.GetEnumerator();
}
}
例:
public class TestA
{
public int MyProperty { get; set; }
}
public class TestB
{
public int MyProperty { get; set; }
}
HashMapDictionary<TestA, TestB> hashMapDictionary = new HashMapDictionary<TestA, TestB>();
var a = new TestA() { MyProperty = 9999 };
var b = new TestB() { MyProperty = 60 };
var b2 = new TestB() { MyProperty = 5 };
hashMapDictionary.Add(a, b);
hashMapDictionary.Add(a, b2);
hashMapDictionary.TryGetValues(a, out List<TestB> result);
foreach (var item in result)
{
//do something
}
iこの単純なクラスを使用します:
public class ListMap<T,V> : List<KeyValuePair<T, V>>
{
public void Add(T key, V value) {
Add(new KeyValuePair<T, V>(key, value));
}
public List<V> Get(T key) {
return FindAll(p => p.Key.Equals(key)).ConvertAll(p=> p.Value);
}
}
使用法:
var fruits = new ListMap<int, string>();
fruits.Add(1, "apple");
fruits.Add(1, "orange");
var c = fruits.Get(1).Count; //c = 2;
Uは、複合文字列キーを構築するメソッドを定義できます 辞書uを使用するすべての場所で、このメソッドを使用してキーを作成する必要があります 例:
private string keyBuilder(int key1, int key2)
{
return string.Format("{0}/{1}", key1, key2);
}
使用目的:
myDict.ContainsKey(keyBuilder(key1, key2))
重複キーは、ディクショナリの契約全体を破壊します。辞書では、各キーは一意であり、単一の値にマップされます。オブジェクトを任意の数の追加オブジェクトにリンクする場合、最善の策はDataSetに似たもの(一般的にはテーブル)です。キーを一方の列に、値をもう一方の列に入れます。これは辞書よりも大幅に遅くなりますが、キーオブジェクトをハッシュする機能を失うためのトレードオフです。
これも可能です:
Dictionary<string, string[]> previousAnswers = null;
これにより、一意のキーを使用できます。これがあなたの役に立つことを願っています。
次のように、大文字と小文字を変えて同じキーを追加できます。
key1
Key1
KEY1
KeY1
kEy1
keY1
ダミーの回答であることは知っていますが、私のために働きました。