web-dev-qa-db-ja.com

C#辞書単一のキーに複数の値を追加するには?

辞書オブジェクトを作成しました

_Dictionary<string, List<string>> dictionary =
    new Dictionary<string,List<string>>();
_

特定の単一キーの文字列のリストに文字列値を追加したい。キーがまだ存在しない場合は、新しいキーを追加する必要があります。 _List<string>_は事前定義されていません。つまり、リストオブジェクトを作成せずにdictionary.Add("key",Listname)に提供しました。 dictionary.Add("key",Listname)でこのリストオブジェクトを動的に作成し、このリストに文字列を追加する方法。 100個のキーを追加する必要がある場合、_dictionary.Add_命令を実行する前に100個のリストを作成する必要がありますか。また、このリストの内容をpedefineする必要がありますか?

ありがとうございました。

21
sailer

あなたが望むものを理解した場合:

dictionary.Add("key", new List<string>()); 

後...

dictionary["key"].Add("string to your list");
8
Reniuz
Dictionary<string, List<string>> dictionary = new Dictionary<string,List<string>>();

foreach(string key in keys) {
    if(!dictionary.ContainsKey(key)) {
        //add
        dictionary.Add(key, new List<string>());
    }
    dictionary[key].Add("theString");
}

キーが存在しない場合、新しいListが追加されます(if内)。それ以外の場合はキーが存在するため、そのキーの下のListに新しい値を追加します。

6
Zelter Ady

Dictionary<K, List<V>>から派生したマルチマップの実装を使用できます。完全ではありませんが、良い仕事をします。

/// <summary>
/// Represents a collection of keys and values.
/// Multiple values can have the same key.
/// </summary>
/// <typeparam name="TKey">Type of the keys.</typeparam>
/// <typeparam name="TValue">Type of the values.</typeparam>
public class MultiMap<TKey, TValue> : Dictionary<TKey, List<TValue>>
{

    public MultiMap()
        : base()
    {
    }

    public MultiMap(int capacity)
        : base(capacity)
    {
    }

    /// <summary>
    /// Adds an element with the specified key and value into the MultiMap. 
    /// </summary>
    /// <param name="key">The key of the element to add.</param>
    /// <param name="value">The value of the element to add.</param>
    public void Add(TKey key, TValue value)
    {
        List<TValue> valueList;

        if (TryGetValue(key, out valueList)) {
            valueList.Add(value);
        } else {
            valueList = new List<TValue>();
            valueList.Add(value);
            Add(key, valueList);
        }
    }

    /// <summary>
    /// Removes first occurence of an element with a specified key and value.
    /// </summary>
    /// <param name="key">The key of the element to remove.</param>
    /// <param name="value">The value of the element to remove.</param>
    /// <returns>true if the an element is removed;
    /// false if the key or the value were not found.</returns>
    public bool Remove(TKey key, TValue value)
    {
        List<TValue> valueList;

        if (TryGetValue(key, out valueList)) {
            if (valueList.Remove(value)) {
                if (valueList.Count == 0) {
                    Remove(key);
                }
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// Removes all occurences of elements with a specified key and value.
    /// </summary>
    /// <param name="key">The key of the elements to remove.</param>
    /// <param name="value">The value of the elements to remove.</param>
    /// <returns>Number of elements removed.</returns>
    public int RemoveAll(TKey key, TValue value)
    {
        List<TValue> valueList;
        int n = 0;

        if (TryGetValue(key, out valueList)) {
            while (valueList.Remove(value)) {
                n++;
            }
            if (valueList.Count == 0) {
                Remove(key);
            }
        }
        return n;
    }

    /// <summary>
    /// Gets the total number of values contained in the MultiMap.
    /// </summary>
    public int CountAll
    {
        get
        {
            int n = 0;

            foreach (List<TValue> valueList in Values) {
                n += valueList.Count;
            }
            return n;
        }
    }

    /// <summary>
    /// Determines whether the MultiMap contains an element with a specific
    /// key / value pair.
    /// </summary>
    /// <param name="key">Key of the element to search for.</param>
    /// <param name="value">Value of the element to search for.</param>
    /// <returns>true if the element was found; otherwise false.</returns>
    public bool Contains(TKey key, TValue value)
    {
        List<TValue> valueList;

        if (TryGetValue(key, out valueList)) {
            return valueList.Contains(value);
        }
        return false;
    }

    /// <summary>
    /// Determines whether the MultiMap contains an element with a specific value.
    /// </summary>
    /// <param name="value">Value of the element to search for.</param>
    /// <returns>true if the element was found; otherwise false.</returns>
    public bool Contains(TValue value)
    {
        foreach (List<TValue> valueList in Values) {
            if (valueList.Contains(value)) {
                return true;
            }
        }
        return false;
    }

}

Addメソッドは、キーが既に存在するかどうかを確認することに注意してください。キーが新しい場合、新しいリストが作成され、値がリストに追加され、リストが辞書に追加されます。キーが既に存在していた場合、新しい値が既存のリストに追加されます。

他のほとんどの回答とほぼ同じですが、これが最も効率的で簡潔な方法だと思います。 TryGetValueを使用する方が、ContainsKeyを使用して他のソリューションが示しているように辞書にインデックスを再作成するよりも高速です。

void Add(string key, string val)
{
    List<string> list;

    if (!dictionary.TryGetValue(someKey, out list))
    {
       values = new List<string>();
       dictionary.Add(key, list);
    }

    list.Add(val);
}
2
roken

NameValuedCollectionを使用します。

適切な出発点は ここ です。リンクからまっすぐ。

System.Collections.Specialized.NameValueCollection myCollection
    = new System.Collections.Specialized.NameValueCollection();

  myCollection.Add(“Arcane”, “http://arcanecode.com”);
  myCollection.Add(“PWOP”, “http://dotnetrocks.com”);
  myCollection.Add(“PWOP”, “http://dnrtv.com”);
  myCollection.Add(“PWOP”, “http://www.hanselminutes.com”);
  myCollection.Add(“TWIT”, “http://www.twit.tv”);
  myCollection.Add(“TWIT”, “http://www.twit.tv/SN”);
2
Sandeep

辞書を使用する代わりに、ILookupに変換してみませんか?

var myData = new[]{new {a=1,b="frog"}, new {a=1,b="cat"}, new {a=2,b="giraffe"}};
ILookup<int,string> lookup = myData.ToLookup(x => x.a, x => x.b);
IEnumerable<string> allOnes = lookup[1]; //enumerable of 2 items, frog and cat

ILookupは、キーごとに複数の値を許可する不変のデータ構造です。異なる時間にアイテムを追加する必要がある場合、おそらくあまり使用されませんが、すべてのデータを事前に用意している場合、これは間違いなく進むべき方法です。

0
spender

辞書の既存のキーにリストを追加しようとして、次の解決策に到達しました:

Dictionary<string,List<string>> NewParent = new Dictionary<string,List<string>>();
child = new List<string> ();
child.Add('SomeData');
NewParent["item1"].AddRange(child);

例外は表示されず、以前の値は置き換えられません。

0
superB

ここに1つの答えの多くのバリエーションがあります:)私はもう1つであり、拡張メカニズムを快適な実行方法として使用します(便利):

public static void AddToList<T, U>(this IDictionary<T, List<U>> dict, T key, U elementToList)
{

    List<U> list;

    bool exists = dict.TryGetValue(key, out list);

    if (exists)
    {
        dict[key].Add(elementToList);
    }
    else
    {
        dict[key] = new List<U>();
        dict[key].Add(elementToList);
    }

}

次に、次のように使用します。

Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();

dict.AddToList(4, "test1");
dict.AddToList(4, "test2");
dict.AddToList(4, "test3");

dict.AddToList(5, "test4");
0
Bronek

NuGetパッケージ Microsoft Experimental Collections があります。これには、必要なことを正確に行うクラスMultiValueDictionaryが含まれています。

ここ は、パッケージの作成者のブログ投稿であり、さらに詳しく説明しています。

ここ は、好奇心が強い場合の別のブログ投稿です。

使用例:

MultiDictionary<string, int> myDictionary = new MultiDictionary<string, int>();
myDictionary.Add("key", 1);
myDictionary.Add("key", 2);
myDictionary.Add("key", 3);
//myDictionary["key"] now contains the values 1, 2, and 3
0
Domysee

文字列を追加するときは、キーが既に存在するかどうかによって異なる方法で行います。キーvalueに文字列keyを追加するには:

List<string> list;
if (dictionary.ContainsKey(key)) {
  list = dictionary[key];
} else {
  list = new List<string>();
  dictionary.Add(ley, list);
}
list.Add(value);
0
Guffa