c#字典如何为单个键添加多个值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10089850/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 12:24:15  来源:igfitidea点击:

c# dictionary How to add multiple values for single key?

c#listdictionary

提问by sailer

I have created dictionary object

我已经创建了字典对象

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

I want to add string values to the list of string for a given single key. If the key doesn't already exists then I have to add a new key. List<string>is not predefined, I mean I didn't create any list object and then supplied to dictionary.Add("key",Listname). How to create dynamically this list object in dictionary.Add("key",Listname)and then add strings to this list. If I have to add 100 keys then do I have to create 100 lists before executing dictionary.Addinstruction and also do I have to pedefine the contents of this lists ?

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

Thank you.

谢谢你。

采纳答案by Adam Houldsworth

Update:check for existence using TryGetValueto do only one lookup in the case where you have the list:

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

List<int> list;

if (!dictionary.TryGetValue("foo", out list))
{
    list = new List<int>();
    dictionary.Add("foo", list);
}

list.Add(2);



Original:原文:检查存在并添加一次,然后键入字典以获取列表并正常添加到列表中:

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

Or List<string>as in your case.

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

As an aside, if you know how many items you are going to add to a dynamic collection such as List<T>, favour the constructor that takes the initial list capacity: new List<int>(100);.

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

This will grab the memory required to satisfy the specified capacity upfront, instead of grabbing small chunks every time it starts to fill up. You can do the same with dictionaries if you know you have 100 keys.

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

回答by Renatas M.

If I understood what you want:

如果我明白你想要什么:

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

later...

之后...

dictionary["key"].Add("string to your list");

回答by Guffa

When you add a string, do it differently depending on whether the key exists already or not. To add the string valuefor the key key:

添加字符串时,根据键是否已存在,执行不同的操作。要value为键添加字符串key

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

回答by Olivier Jacot-Descombes

You could use my implementation of a multimap, which derives from a Dictionary<K, List<V>>. It is not perfect, however it does a good job.

您可以使用我的 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;
    }

}

Note that the Addmethod looks if a key is already present. If the key is new, a new list is created, the value is added to the list and the list is added to the dictionary. If the key was already present, the new value is added to the existing list.

请注意,该Add方法会查看密钥是否已存在。如果键是新的,则创建一个新列表,将值添加到列表中,并将列表添加到字典中。如果键已经存在,新值将添加到现有列表中。

回答by Zelter Ady

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

If the key doesn't exist, a new Listis added (inside if). Else the key exists, so just add a new value to the Listunder that key.

如果键不存在,List则添加一个新键(在 if 内)。否则键存在,所以只需List在该键下添加一个新值。

回答by roken

Though nearly the same as most of the other responses, I think this is the most efficient and concise way to implement it. Using TryGetValue is faster than using ContainsKey and reindexing into the dictionary as some other solutions have shown.

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

回答by spender

Instead of using a Dictionary, why not convert to an ILookup?

而不是使用字典,为什么不转换为 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

An ILookup is an immutable data structure that allows multiple values per key. Probably not much use if you need to add items at different times, but if you have all your data up-front, this is definitely the way to go.

ILookup 是一种不可变的数据结构,允许每个键有多个值。如果您需要在不同时间添加项目,可能没有太大用处,但如果您预先拥有所有数据,这绝对是要走的路。

回答by Sandeep

Use NameValuedCollection.

使用 NameValuedCollection。

Good starting point is here. Straight from the link.

好的起点就在这里。直接从链接。

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

回答by Bronek

Here are many variations of the one answer :) My is another one and it uses extension mechanism as comfortable way to execute (handy):

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

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

}

Then you use it as follows:

然后按如下方式使用它:

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

回答by Domysee

There is a NuGet package Microsoft Experimental Collectionsthat contains a class MultiValueDictionarywhich does exactly what you need.

有一个 NuGet 包Microsoft Experimental Collections,其中包含一个MultiValueDictionary完全符合您需要的类。

Hereis a blog post of the creator of the package that describes it further.

是软件包创建者的博客文章,进一步描述了它。

Hereis another blog post if you're feeling curious.

如果您感到好奇,这里是另一篇博文。

Example Usage:

示例用法:

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