c# - 在 C# 中使用 LINQ 反转字典

标签 c# linq dictionary

如何转换

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> 中的每个元素事实上,它是独一无二的。在这种情况下,一个简单的 SelectManyToDictionary会完成你所需要的; 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/

相关文章:

c# - 在 where 表达式中使用 Guid.Empty 挂起 Linq 查询

c# - LINQ 将 Dictionary<key,value> 转换为 Dictionary<value,key>

Swift 4 : Find value in nested, 动态字典 <String, Any> 递归

c# - 如何删除 lambda 表达式的 Where 条件?

c# - 无需安装oracle客户端的oracle远程连接

c# - ManualResetEvent 未始终如一地释放所有等待线程的问题

c# - 无论大小如何,如果源较新,则只复制 MSBuild 复制任务

c# - 是否可以从空变量开始联合?

c# - 如何像在 Java 中使用 Hashtable 一样使用 C# 泛型字典?

C++ Multimap 插入函数