如何转换
Dictioanry<String,List<String>> into Dictionary<String,String>
我有一本像这样的字典
Dictioanry<String,List<String>>dictOne=new Dictionary<String,List<String>>();
其中包含
Key(String) Value(List<String>)
A a1,a2
B b1,b2
C c1
我需要将“dictOne”转换成
Dictionary<String,String> dictReverse=new Dictionary<String,String>()
所以结果会是这样
Key(String) Value(String)
a1 A
a2 A
b1 B
b2 B
c1 C
有没有办法使用 LINQ 来做到这一点
提前致谢
最佳答案
更新:正如其他人指出的那样,为了使字典以这种方式真正“可逆”,您的 List<string>
中的值对象都需要是唯一的;否则,您无法创建 Dictionary<string, string>
源字典中的每个值都有一个条目,因为会有重复的键。
例子:
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
用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>>
-- 仅举几个任意示例来展示其灵 active 。
(说明此方法的测试程序位于此答案的底部。)
选项 2:跳过重复项
如果您的 List<string>
中有重复元素values 是您希望能够在不抛出异常的情况下处理的现实场景,我建议您看一下 Gabe's excellent answer对于使用 GroupBy
的方法(实际上,Gabe 还提供了一种灵活的方法,可以基于选择器函数涵盖这两种情况中的任何一种;但是,如果您肯定想要重复,我仍然建议使用上述方法,因为它应该比使用 GroupBy
便宜一些)。
示例程序
这里有一个小测试程序,用于说明上面关于 Dictionary<string, List<string>>
的选项 1在其 List<string>
中没有重复的元素值(value)观:
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);
}
输出:
a1: A a2: A b1: B b2: B c1: C
关于c# - 在 C# 中使用 LINQ 反转字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3697973/