C# 阿扁词典<;字符串,HashSet<;字符串>&燃气轮机;

C# 阿扁词典<;字符串,HashSet<;字符串>&燃气轮机;,c#,dictionary,hashset,C#,Dictionary,Hashset,这件事我已经搞了好几天了,我都想不起来了: 我的结构如下: Dictionary<string, HashSet<string>> 其中,p前缀值是字典键,S前缀值是哈希集值 我需要的是以下输出列表 P1, P2, S1, S2 在这种情况下,我将具有以下起始值: P1 S1, S2 P2 S1 输出列表应为: P1, P2, S1, P1, S2 如果在几个字典项的哈希集中有相似的值,它应该将它们组合在一起,这就是为什么P1,P2有S1,P1只有

这件事我已经搞了好几天了,我都想不起来了:

我的结构如下:

Dictionary<string, HashSet<string>>
其中,p前缀值是字典键,S前缀值是哈希集值

我需要的是以下输出列表

P1, P2, S1, S2
在这种情况下,我将具有以下起始值:

P1     S1, S2
P2     S1
输出列表应为:

P1, P2, S1, P1, S2
如果在几个字典项的哈希集中有相似的值,它应该将它们组合在一起,这就是为什么P1,P2有S1,P1只有S2

下面是一个小测试页,可以进一步说明:

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();
}
static void Main(字符串[]args)
{
var start=newdictionary();
var输出=新列表();
//例1
添加(“P1”,新哈希集{“S1”,“S2”});
添加(“P2”,新哈希集{“S1”,“S2”});
输出=HocusPocus(启动);
PrintResult(输出);//应该是P1、P2、S1、S2
//例2
start.Clear();
添加(“P1”,新哈希集{“S1”,“S2”});
Add(“P2”,新哈希集{“S1”});
输出=HocusPocus(启动);
PrintResult(输出);//应该是P1、P2、S1、P1、S2
//例3
start.Clear();
添加(“P1”,新哈希集{“S1”、“S2”、“S3”});
Add(“P2”,新哈希集{“S1”});
Add(“P3”,新哈希集{“S1”,“S2”});
输出=HocusPocus(启动);
PrintResult(输出);//应该是P1、P2、P3、S1、P1、P3、S2、P1、S3
Console.ReadKey();
}
公共静态列表HocusPocus(字典数据)
{
//魔法在这里发生
}
公共静态无效打印结果(列表结果)
{
result.ForEach(x=>Console.Write($“{x},”);
Console.WriteLine();
}

对于每个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" } }
};
要能够按p值序列分组,需要一个
IEqualityComparer

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());
        }
    }
}
您可以打印查找:

foreach (var items in lookup)
{
    Console.Write(string.Join(" ", items.Key));
    Console.Write(" ");
    Console.WriteLine(string.Join(" ", items));
}

似乎每个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" } }
};
要能够按p值序列分组,需要一个
IEqualityComparer

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());
        }
    }
}
您可以打印查找:

foreach (var items in lookup)
{
    Console.Write(string.Join(" ", items.Key));
    Console.Write(" ");
    Console.WriteLine(string.Join(" ", items));
}
下面是的一个版本,它遍历主字典一次以构建反向字典,并使用集合而不是序列(它也在原始方法签名中工作):

公共静态列表HocusPocus(字典数据)
{
var invert=新字典();
foreach(数据中的var kvp)
{
foreach(以kvp.值表示的var s)
{
如果(!invert.TryGetValue,out var pvalues))
{
pvalues=新的HashSet();
反转[s]=pvalues;
}
pvalues.Add(kvp.Key);
}
}
变量查找=反转
.ToLookup(=>0.Value,=>0.Key,new SetComparer());
var flat=新列表();
foreach(查找中的变量项)
{
flat.AddRange(项.键);
平面。添加范围(项目);
}
返回平面;
}
公共类集合比较程序:IEqualityComparer
{
公共布尔等于(ISet x,ISet y)
{
返回x.SetEquals(y);
}
公共int GetHashCode(ISet obj)
{
未经检查
{
int hash=19;
foreach(对象中的变量foo)
{
hash=hash*31+foo.GetHashCode();
}
返回散列;
}
}
}
以下是的一个版本,它遍历主字典一次以构建反向字典,并使用集合而不是序列(它也可以在原始方法签名中工作):

公共静态列表HocusPocus(字典数据)
{
var invert=新字典();
foreach(数据中的var kvp)
{
foreach(以kvp.值表示的var s)
{
如果(!invert.TryGetValue,out var pvalues))
{
pvalues=新的HashSet();
反转[s]=pvalues;
}
pvalues.Add(kvp.Key);
}
}
变量查找=反转
.ToLookup(=>0.Value,=>0.Key,new SetComparer());
var flat=新列表();
foreach(查找中的变量项)
{
flat.AddRange(项.键);
平面。添加范围(项目);
}
返回平面;
}
公共类集合比较程序:IEqualityComparer
{
公共布尔等于(ISet x,ISet y)
{
返回x.SetEquals(y);
}
公共int GetHashCode(ISet obj)
{
未经检查
{
int hash=19;
foreach(对象中的变量foo)
{
hash=hash*31+foo.GetHashCode();
}
返回散列;
}
}
}

您能更明确地说明您真正想要发生什么吗?我可以试着从你的输出中猜出来,但并不十分清楚。什么是P和S?当你创建一个字符串的散列集时,你通常会使用一个不属于普通数据的字符进行合并,比如“P1^P2^S1^P1^S2”。你试过什么吗?我们为什么要做你的工作?构建一个循环来迭代字典并将值放入扁平化列表并不难。不管怎样,输出应该是
P1、P2、S1、S2
还是
P1、P2、S1、P1、S2
。当然,我已经尝试了一些方法,比如循环之类的,但这只是我目前为止所做的。它是收集字典键、比较HashSet值、求交这些值的组合……您能更明确地说明您实际希望发生什么吗?我可以试着从你的输出中猜出来,但并不十分清楚。什么是P和S?当你创建一个字符串的散列集时,你通常会使用一个不属于普通数据的字符进行合并,比如“P1^P2^S1^P1^S2”。你试过什么吗?我们为什么要做你的工作?建立一个循环来重复你的措辞并不难
public static List<string> HocusPocus(Dictionary<string, HashSet<string>> data)
{
    var invert = new Dictionary<string, HashSet<string>>();

    foreach (var kvp in data)
    {
        foreach (var s in kvp.Value)
        {
            if (!invert.TryGetValue(s, out var pvalues))
            {
                pvalues = new HashSet<string>();
                invert[s] = pvalues;
            }

            pvalues.Add(kvp.Key);
        }
    }

    var lookup = invert
        .ToLookup(_ => _.Value, _ => _.Key, new SetComparer());

    var flat = new List<string>();

    foreach (var item in lookup)
    {
        flat.AddRange(item.Key);
        flat.AddRange(item);
    }

    return flat;
}


public class SetComparer : IEqualityComparer<ISet<string>>
{
    public bool Equals(ISet<string> x, ISet<string> y)
    {
        return x.SetEquals(y);
    }

    public int GetHashCode(ISet<string> obj)
    {
        unchecked
        {
            int hash = 19;
            foreach (var foo in obj)
            {
                hash = hash * 31 + foo.GetHashCode();
            }
            return hash;
        }
    }
}