J'ai créé un objet dictionnaire
Dictionary<string, List<string>> dictionary =
new Dictionary<string,List<string>>();
Je souhaite ajouter des valeurs de chaîne à la liste de chaînes pour une clé unique donnée . Si la clé n'existe pas déjà, je dois ajouter une nouvelle clé. List<string>
n'est pas prédéfini, je veux dire que je n'ai créé aucun objet de liste, puis fourni à dictionary.Add("key",Listname)
. Comment créer dynamiquement cet objet de liste dans dictionary.Add("key",Listname)
puis ajouter des chaînes à cette liste. Si je dois ajouter 100 clés, dois-je créer 100 listes avant d'exécuter l'instruction dictionary.Add
et dois-je également définir le contenu de ces listes?
Je vous remercie.
Mise à jour: vérifie l'existence à l'aide de TryGetValue
pour ne faire qu'une recherche dans le cas où vous avez la liste:
List<int> list;
if (!dictionary.TryGetValue("foo", out list))
{
list = new List<int>();
dictionary.Add("foo", list);
}
list.Add(2);
var dictionary = new Dictionary<string, List<int>>();
if (!dictionary.ContainsKey("foo"))
dictionary.Add("foo", new List<int>());
dictionary["foo"].Add(42);
dictionary["foo"].AddRange(oneHundredInts);
Ou List<string>
comme dans votre cas.
Soit dit en passant, si vous savez combien d'éléments vous allez ajouter à une collection dynamique telle que List<T>
, privilégiez le constructeur prenant la capacité de liste initiale: new List<int>(100);
.
Cela récupérera la mémoire requise pour satisfaire la capacité spécifiée upfront, au lieu de récupérer de petits morceaux à chaque fois qu'il commence à se remplir. Vous pouvez faire la même chose avec les dictionnaires si vous savez que vous avez 100 clés.
Si j'ai compris ce que tu veux:
dictionary.Add("key", new List<string>());
plus tard...
dictionary["key"].Add("string to your list");
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");
}
Si la clé n'existe pas, une nouvelle List
est ajoutée (à l'intérieur de si). Si la clé existe, il suffit d'ajouter une nouvelle valeur à la variable List
sous cette clé.
Vous pourriez utiliser mon implémentation d'une carte multiple, qui dérive d'un Dictionary<K, List<V>>
. Ce n'est pas parfait, mais cela fait du bon travail.
/// <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;
}
}
Notez que la méthode Add
recherche si une clé est déjà présente. Si la clé est nouvelle, une nouvelle liste est créée, la valeur est ajoutée à la liste et la liste est ajoutée au dictionnaire. Si la clé était déjà présente, la nouvelle valeur est ajoutée à la liste existante.
Bien que presque identique à la plupart des autres réponses, je pense que c'est la manière la plus efficace et la plus concise de la mettre en œuvre. L'utilisation de TryGetValue est plus rapide que l'utilisation de ContainsKey et la réindexation dans le dictionnaire, comme le montrent d'autres solutions.
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);
}
Utilisez NameValuedCollection.
Bon point de départ est ici . Directement du lien.
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”);
Au lieu d'utiliser un dictionnaire, pourquoi ne pas convertir en 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 est une structure de données immuable qui permet plusieurs valeurs par clé. Ce n'est probablement pas très utile si vous devez ajouter des éléments à des moments différents, mais si vous avez toutes vos données à l'avance, c'est certainement la voie à suivre.
J'essayais d'ajouter List à une clé existante dans le dictionnaire et j'ai atteint la solution suivante:
Dictionary<string,List<string>> NewParent = new Dictionary<string,List<string>>();
child = new List<string> ();
child.Add('SomeData');
NewParent["item1"].AddRange(child);
Il ne montrera aucune exception et ne remplacera pas les valeurs précédentes.
Voici plusieurs variantes de la réponse :) My en est une autre et utilise le mécanisme d’extension comme moyen pratique d’exécuter (pratique):
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);
}
}
Ensuite, vous l'utilisez comme suit:
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");
Il existe un package NuGet Microsoft Experimental Collections qui contient une classe MultiValueDictionary
qui répond exactement à vos besoins.
Ici est un article de blog du créateur du paquet qui le décrit plus en détail.
Ici est un autre article de blog si vous vous sentez curieux.
Exemple d'utilisation:
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
Lorsque vous ajoutez une chaîne, procédez différemment selon que la clé existe déjà ou non. Pour ajouter la chaîne value
à la clé key
:
List<string> list;
if (dictionary.ContainsKey(key)) {
list = dictionary[key];
} else {
list = new List<string>();
dictionary.Add(ley, list);
}
list.Add(value);