.NET词典中的重复键?

243 .net c# dictionary multimap

.NET基类库中是否有允许使用重复键的字典类?我发现的唯一解决方案是创建一个类,例如:

Dictionary<string, List<object>>
Run Code Online (Sandbox Code Playgroud)

但这对实际使用非常恼火.在Java中,我相信MultiMap可以实现这一点,但是在.NET中找不到模拟.

Jon*_*eet 221

如果您使用的是.NET 3.5,请使用Lookup该类.

编辑:您通常创建一个Lookup使用Enumerable.ToLookup.这确实假设您之后不需要更改它 - 但我通常发现它足够好.

如果为你工作,我不认为有在框架中,这将有助于东西-和使用字典是好得不能再好:(

  • *注意事项*:`Lookup`不可序列化 (28认同)
  • @Josh:您使用Enumerable.ToLookup创建一个. (3认同)
  • 我们应该如何向该 Lookup 添加项目? (2认同)

小智 160

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案在功能上有效,但List的实现不知道密钥或值,并且根本无法优化对密钥的搜索 (29认同)

Hec*_*rea 39

以下是使用List <KeyValuePair <string,string >>的方法

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);
}
Run Code Online (Sandbox Code Playgroud)

输出k1 = v1,k1 = v2,k1 = v3


Mat*_*att 21

如果您使用字符串作为键和值,则可以使用System.Collections.Specialized.NameValueCollection,它将通过GetValues(字符串键)方法返回字符串值数组.

  • NameValueCollection不允许多个键. (6认同)

小智 18

我刚刚遇到了PowerCollections库,其中包括一个名为MultiDictionary的类.这整齐地包装了这种类型的功能.


The*_*edi 14

关于使用Lookup的非常重要的注意事项:

您可以Lookup(TKey, TElement)通过调用ToLookup实现的对象来创建a的实例IEnumerable(T)

没有公共构造函数来创建a的新实例Lookup(TKey, TElement).此外,Lookup(TKey, TElement)对象是不可变的,也就是说,Lookup(TKey, TElement)在创建对象后,无法在对象中添加或删除元素或键.

(来自MSDN)

我认为这对于大多数用途来说都是显示器.

  • 我可以想到很少有用它会成为一个显示塞子.但是,我认为不可变的对象很棒. (6认同)
  • @JoelMueller 我能想到很多情况下这是一个表演障碍。必须重新创建一个字典来添加一个项目并不是一个特别有效的解决方案...... (2认同)

MAD*_*Map 10

我觉得像List<KeyValuePair<object, object>>约伯这样的事情.

  • @wizlib:唯一的方法是遍历列表,这不像散列那样有效.-1 (2认同)

小智 9

如果您使用的是> = .NET 4,则可以使用TupleClass:

// 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());
}
Run Code Online (Sandbox Code Playgroud)

  • 这看起来像上面的“List&lt;KeyValuePair&lt;key, value&gt;&gt;”解决方案。我错了吗? (2认同)

Chr*_*heD 5

“滚动自己的”字典版本很容易,该字典允许“重复键”条目。这是一个简单的简单实现。您可能要考虑增加对上大多数(如果不是全部)的支持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];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

有关如何使用它的快速示例:

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));
}
Run Code Online (Sandbox Code Playgroud)


小智 5

由于新的 C#(我相信它来自 7.0),您还可以执行以下操作:

var duplicatedDictionaryExample = new List<(string Key, string Value)> { ("", "") ... }
Run Code Online (Sandbox Code Playgroud)

并且您将它用作标准列表,但是有两个值可以随意命名

foreach(var entry in duplicatedDictionaryExample)
{ 
    // do something with the values
    entry.Key;
    entry.Value;
}
Run Code Online (Sandbox Code Playgroud)