30

我创建了字典对象

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

我想将字符串值添加到给定单个键的字符串列表中。如果密钥不存在,那么我必须添加一个新密钥。List<string>不是预定义的,我的意思是我没有创建任何列表对象,然后提供给dictionary.Add("key",Listname). 如何在其中动态创建此列表对象dictionary.Add("key",Listname),然后将字符串添加到此列表中。如果我必须添加 100 个键,那么我是否必须在执行dictionary.Add指令之前创建 100 个列表,并且我是否必须定义这些列表的内容?

谢谢你。

4

12 回答 12

38

更新:TryGetValue在您拥有列表的情况下,仅使用一次查找来检查是否存在:

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);

或者List<string>就像你的情况一样。

顺便说一句,如果您知道要向动态集合中添加多少项,例如List<T>,请支持采用初始列表容量的构造函数:new List<int>(100);

这将预先获取满足指定容量所需的内存,而不是每次开始填满时都抓取小块。如果你知道你有 100 个键,你可以对字典做同样的事情。

于 2012-04-10T13:37:11.193 回答
9

如果我明白你想要什么:

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

之后...

dictionary["key"].Add("string to your list");
于 2012-04-10T13:37:33.343 回答
6
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在该键下添加一个新值。

于 2012-04-10T13:41:12.840 回答
4

您可以使用我的 multimap 实现,它派生自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方法会查看密钥是否已存在。如果键是新的,则创建一个新列表,将值添加到列表中,并将列表添加到字典中。如果键已经存在,则将新值添加到现有列表中。

于 2012-04-10T13:39:23.350 回答
3

使用 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”);
于 2012-04-10T14:31:39.020 回答
2

尽管与大多数其他响应几乎相同,但我认为这是实现它的最有效和最简洁的方式。正如其他一些解决方案所示,使用 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);
}
于 2012-04-10T13:45:57.470 回答
0

添加字符串时,请根据键是否已存在而有所不同。value要为键添加字符串key

List<string> list;
if (dictionary.ContainsKey(key)) {
  list = dictionary[key];
} else {
  list = new List<string>();
  dictionary.Add(ley, list);
}
list.Add(value);
于 2012-04-10T13:38:33.063 回答
0

这是一个答案的许多变体:)我是另一个答案,它使用扩展机制作为执行的舒适方式(方便):

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");
于 2013-06-27T14:17:57.433 回答
0

为什么不使用字典,而不是转换为 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 是一个不可变的数据结构,它允许每个键有多个值。如果您需要在不同时间添加项目,可能没有多大用处,但如果您预先准备好所有数据,这绝对是要走的路。

于 2012-04-10T13:46:58.160 回答
0

使用来自ConcurrentDictionary的AddOrUpdate有一种“单命令行”方式:

using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
 
...

var dictionary = new ConcurrentDictionary<string, IEnumerable<string>>();
var itemToAdd = "item to add to key-list";

dictionary.AddOrUpdate("key", new[]{itemToAdd}, (key,list) => list.Append(itemToAdd));

// If "key" doesn't exist, creates it with a list containing itemToAdd as value
// If "key" exists, adds item to already existent list (third parameter)
于 2021-03-10T22:01:27.560 回答
0

有一个 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
于 2015-10-01T12:33:24.390 回答
0

我试图将 List 添加到字典中的现有键并达到以下解决方案:

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

它不会显示任何异常,也不会替换以前的值。

于 2015-12-01T11:33:38.757 回答