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