Update:正如其他人所指出的,为了使字典真正以这种方式“可逆”,values在你的List<string>
对象必须都是唯一的;否则,您无法创建Dictionary<string, string>
源字典中的每个值都有一个条目,因为会有重复的键。
Example:
var dictOne = new Dictionary<string, List<string>>
{
{ "A", new List<string> { "a1", "a2" } },
{ "B", new List<string> { "b1", "b2" } },
{ "C", new List<string> { "c1", "a2" } } // duplicate!
};
您(至少)有两种选择来处理这个问题。
选项 1:添加重复项
您可能希望确保每个中的每个元素List<string>
事实上,它是独一无二的。在这种情况下,一个简单的SelectMany
with a ToDictionary
会完成你所需要的;这ToDictionary
调用会抛出一个ArgumentException
遇到重复值时:
var dictTwo = dictOne
.SelectMany(kvp => kvp.Value.Select(s => new { Key = s, Value = kvp.Key }))
.ToDictionary(x => x.Key, x => x.Value);
将此功能抽象为自己的方法的最通用方法(想到的)是实现一个扩展方法,该方法可以为任何IDictionary<T, TEnumerable>
实施地点TEnumerable
实施IEnumerable<TValue>
:
// Code uglified to fit within horizonal scroll area
public static Dictionary<T2, T1> ReverseDictionary<T1, T2, TEnumerable>(
this IDictionary<T1, TEnumerable> source) where TEnumerable : IEnumerable<T2>
{
return source
.SelectMany(e => e.Value.Select(s => new { Key = s, Value = e.Key }))
.ToDictionary(x => x.Key, x => x.Value);
}
上述方法中泛型类型参数的丑陋扩散是为了允许除严格类型之外的类型Dictionary<T, List<T>>
: 它可以接受Dictionary<int, string[]>
,例如,或者SortedList<string, Queue<DateTime>>
——只是几个任意的例子来证明它的灵活性。
(说明此方法的测试程序位于本答案的底部。)
选项 2:跳过重复项
如果你的元素中有重复的元素List<string>
value 是一个现实场景,您希望能够在不引发异常的情况下处理它,我建议您看一下加布的出色回答 https://stackoverflow.com/questions/3697973/reversing-dictionary-using-linq-in-c/3698175#3698175对于使用的方法GroupBy
(实际上,Gabe 还提供了一种灵活的方法,可以基于选择器函数涵盖这两种情况中的任何一种;但是,如果您确实想要复制一个,我仍然建议上述方法,因为它应该比使用便宜一些GroupBy
).
示例程序
这是一个小测试程序来说明Option 1上面关于一个Dictionary<string, List<string>>
with 没有重复元素 in its List<string>
values:
var dictOne = new Dictionary<string, List<string>>
{
{ "A", new List<string> { "a1", "a2" } },
{ "B", new List<string> { "b1", "b2" } },
{ "C", new List<string> { "c1" } }
};
// Using ReverseDictionary implementation described above:
var dictTwo = dictOne.ReverseDictionary<string, string, List<string>>();
foreach (var entry in dictTwo)
{
Console.WriteLine("{0}: {1}", entry.Key, entry.Value);
}
Output:
a1: A
a2: A
b1: B
b2: B
c1: C