从具有通用值的字典中获取TKey,其中TValue是List <string>

时间:2019-03-14 11:19:50

标签: 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<string> { "Green","Orange"} },
    {"d" , new List<string> { "Black","Green"} },
};

我需要从dict作为字典输出,其中List<string>中的公用值应该是键,而值应该是键列表。

例如:

Red: [a,b]
Green: [c,d]

我不知道如何使用 list 中的 dictionary 作为 TValue 解决此问题强>。

请解释一下如何在字典中处理列表。

2 个答案:

答案 0 :(得分:5)

您可以使用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());

答案 1 :(得分:3)

很多循环...遍历字典,然后遍历列表中的每个值。

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);
    }
}

如果您要通过一项包含多个项目的条目进行过滤,则可以执行以下操作:

result = result.Where(x => x.Value.Count > 1).ToDictionary(x => x.Key, x => x.Value);

或者,您可以避免循环并改用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());