我现在已经搞乱了几天了,我无法绕过它:
我有以下结构:
Dictionary<string, HashSet<string>>
包含以下数据:
P1 S1, S2
P2 S1, S2
P-prefixed值是字典键,S-prefixed值是HashSet值。
我需要的是以下输出列表,
P1, P2, S1, S2
如果我有以下起始值:
P1 S1, S2
P2 S1
输出列表应为:
P1, P2, S1, P1, S2
如果在几个字典项的HashSet中有类似的值,它应该将它们组合在一起,这就是为什么P1,P2有S1,P1只有S2
这是一个澄清更多的TestApp:
static void Main(string[] args)
{
var start = new Dictionary<string, HashSet<string>>();
var output = new List<string>();
//example1
start.Add("P1", new HashSet<string> { "S1", "S2" });
start.Add("P2", new HashSet<string> { "S1", "S2" });
output = HocusPocus(start);
PrintResult(output); // should be P1, P2, S1, S2
//example 2
start.Clear();
start.Add("P1", new HashSet<string> { "S1", "S2" });
start.Add("P2", new HashSet<string> { "S1" });
output = HocusPocus(start);
PrintResult(output); // should be P1, P2, S1, P1, S2
//example 3
start.Clear();
start.Add("P1", new HashSet<string> { "S1", "S2", "S3" });
start.Add("P2", new HashSet<string> { "S1" });
start.Add("P3", new HashSet<string> { "S1", "S2" });
output = HocusPocus(start);
PrintResult(output); // should be P1, P2, P3, S1, P1, P3, S2, P1, S3
Console.ReadKey();
}
public static List<string> HocusPocus(Dictionary<string, HashSet<string>> data)
{
// magic happens here
}
public static void PrintResult(List<string> result)
{
result.ForEach(x => Console.Write($"{x},"));
Console.WriteLine();
}
答案 0 :(得分:3)
对于每个S,您似乎想要找到与该S相关联的所有P,并且还使用相同的P值组来分组S值。如果您的数据集不是很大,那么即使不是以最有效的方式,也可以非常简单地完成。
您的数据:
var start = new Dictionary<string, HashSet<string>> {
{ "P1", new HashSet<string> { "S1", "S2", "S3" } },
{ "P2", new HashSet<string> { "S1" } },
{ "P3", new HashSet<string> { "S1", "S2" } }
};
首先,下一次迭代需要所有的S值:
var allSValues = start.SelectMany(kvp => kvp.Value).Distinct();
为了能够按P值序列进行分组,需要IEqualityComparer<IEnumerable<string>>
:
class SequenceEqualityComparer : IEqualityComparer<IEnumerable<string>>
{
// Does not handle null values correctly.
public bool Equals(IEnumerable<string> x, IEnumerable<string> y) => x.SequenceEqual(y);
public int GetHashCode(IEnumerable<string> obj)
{
unchecked {
return obj.Aggregate(17, (hash, @string) => hash * 23*@string.GetHashCode());
}
}
}
(比较应该将输入视为集合,而不是序列,但为此目的,排序是稳定的,因此它将起作用。)
找到每个S值的P值,然后将其分组为一个类似于字典的查找,除了每个键(P值序列)可以有多个值(S值):
var lookup = allSValues.Select(s => new
{
S = s,
PValues = start
.Where(kvp => kvp.Value.Contains(s))
.Select(kvp => kvp.Key)
.ToList()
})
.ToLookup(item => item.PValues, item => item.S, new SequenceEqualityComparer());
您可以打印查找:
foreach (var items in lookup)
{
Console.Write(string.Join(" ", items.Key));
Console.Write(" ");
Console.WriteLine(string.Join(" ", items));
}
答案 1 :(得分:1)
这是Martin's的一个版本,用于遍历主要字典以构建反向字典,并使用集合而不是序列(它也适用于原始方法签名):
home1/ja22/public_html/exam