C# 从具有公共值的字典中获取TKey,其中TValue是List<;字符串>;

C# 从具有公共值的字典中获取TKey,其中TValue是List<;字符串>;,c#,dictionary,C#,Dictionary,我有一本字典,看起来像这样: Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>() { {"a" , new List<string> { "Red","Yellow"} }, {"b" , new List<string> { "Blue","Red"} }, {"c" , new List<

我有一本字典,看起来像这样:

Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>()
{
    {"a" , new List<string> { "Red","Yellow"} },
    {"b" , new List<string> { "Blue","Red"} },
    {"c" , new List<string> { "Green","Orange"} },
    {"d" , new List<string> { "Black","Green"} },
};
我不知道如何用
字典中的
列表
作为
TValue来解决这个问题


请告诉我如何处理字典中的列表。

大量循环。。。循环字典,然后循环列表中的每个值

var result = new Dictionary<string, List<string>>();

// Loop through each key/value pair in the dictionary
foreach (var kvp in dict)
{
    // kvp.Key is the key ("a", "b", etc)
    // kvp.Value is the list of values ("Red", "Yellow", etc)

    // Loop through each of the values
    foreach (var value in kvp.Value)
    {
        // See if our results dictionary already has an entry for this
        // value. If so, grab the corresponding list of keys. If not,
        // create a new list of keys and insert it.
        if (!result.TryGetValue(value, out var list))
        {
            list = new List<string>();
            result.Add(value, list);
        }

        // Add our key to this list of keys
        list.Add(kvp.Key);
    }
}
或者,您可以避免循环,而是使用Linq:

// Flatten the dictionary into a set of tuples
// e.g. (a, Red), (a, Yellow), (b, Blue), (b, Red), etc
var result = dict.SelectMany(kvp => kvp.Value.Select(color => (key: kvp.Key, color)))
    // Group by the value, taking the color as the elements of the group
    // e.g. (Red, (a, b)), (Yellow, (a)), etc
    .GroupBy(item => item.color, item => item.key)
    // Filter to the ones with more than one item
    .Where(group => group.Count() > 1)
    // Turn it into a dictionary, taking the key of the grouping
    // (Red, Green, etc), as the dictionary key
    .ToDictionary(group => group.Key, group => group.ToList());
您还可以使用linq查询语法,该语法稍微长一点,但避免了
SelectMany

var result =
    (
        from kvp in dict
        from color in kvp.Value
        group kvp.Key by color into grp
        where grp.Count() > 1
        select grp
    ).ToDictionary(grp => grp.Key, grp => grp.ToList());

您可以使用
SelectMany
来修饰您的字典,并获得如下简单列表

"a" - "Red"
"a" - "Yellow"
"b" - "Blue"
"b" = "Red"
// and so on
然后按值分组,并从这些组中构建一个新词典。请尝试以下代码:

var commonValues = dict.SelectMany(kv => kv.Value.Select(v => new {key = kv.Key, value = v}))
    .GroupBy(x => x.value)
    .Where(g => g.Count() > 1)
    .ToDictionary(g => g.Key, g => g.Select(x => x.key).ToList());

foreach
循环中,它不允许我初始化
TryGetValue()
方法中的
列表。所以我以前也这么做过,为什么会这样?@Watarap你使用的是旧的C#版本。“输出变量”是在C#7.0中引入的。@canton7我使用的是.NET framework 4.7.2,所以我认为C#v7.0 plus。Out对我有效,如果(!result.TryGetValue(value,Out var list))
它不允许我这样声明
。我必须声明list变量
list;如果(!result.TryGetValue(value,out list))
要编译它。@Watarap您需要Visual Studio 2017 for C#7.0。确保在Project->Properties->Build->Advanced->Language version中选择了它。尽管如此,这并不重要——做你所做的很好,结果也是一样的。@canton7你是对的,我实际上在Visual studio 2015中使用了c#6.0,刚刚检查过。最后一个问题是,为什么它抛出的对象在使用它时必须实现IConvertible。此项目不是基于控制台应用程序的,我无法找出导致此错误的原因。
"a" - "Red"
"a" - "Yellow"
"b" - "Blue"
"b" = "Red"
// and so on
var commonValues = dict.SelectMany(kv => kv.Value.Select(v => new {key = kv.Key, value = v}))
    .GroupBy(x => x.value)
    .Where(g => g.Count() > 1)
    .ToDictionary(g => g.Key, g => g.Select(x => x.key).ToList());