C# 如何使用UNION对字符/字符串数组进行分组?

C# 如何使用UNION对字符/字符串数组进行分组?,c#,arrays,linq,grouping,union,C#,Arrays,Linq,Grouping,Union,我有一个二维字符数组,叫做字母[][] Letters[0][0] = A [0][1] = B Letters[1][0] = C [1][1] = D Letters[2][0] = B [2][1] = A [2][2] = F Letters[3][0] = I [3][1] = F [3][2] = J 我需要对它进行分组,所以它将是这样的: group[0] [0] = A group[0]

我有一个二维字符数组,叫做字母[][]

Letters[0][0] = A
       [0][1] = B

Letters[1][0] = C
       [1][1] = D

Letters[2][0] = B
       [2][1] = A
       [2][2] = F

Letters[3][0] = I
       [3][1] = F
       [3][2] = J
我需要对它进行分组,所以它将是这样的:

group[0] [0] = A
group[0] [1] = B
group[0] [2] = F
group[0] [3] = I
group[0] [4] = J

group[1] [0] = C
group[1] [1] = D
到目前为止,我的逻辑是用其他元素检查每个元素。如果两个元素是同一个字母,则它将与整个其他数组元素一起分组,而不包含双重/重复的元素。但是,我不确定是否使用C#Linq Union,或者仅仅使用标准阵列访问


我该怎么做才能以最佳方式将其分组?或者有其他解决方案吗?

我认为纯LINQ解决方案过于复杂。这不是一个简单的联合操作(如果我正确理解您的规范的话)。您希望基于非空交点合并。这意味着必须首先重新排列数据,以便LINQ可以进行连接,以找到匹配的数据,而且由于LINQ只会在相等的条件下进行连接,因此在保留原始分组信息的同时,这样做将导致语法上的麻烦,这将比它值得的麻烦多,IMHO

以下是一种非LINQ方法,适用于您给出的示例:

static void Main(string[] args)
{
    char[][] letters =
    {
        new [] { 'A', 'B' },
        new [] { 'C', 'D' },
        new [] { 'B', 'A', 'F' },
        new [] { 'I', 'F', 'J' },
    };

    List<HashSet<char>> sets = new List<HashSet<char>>();

    foreach (char[] row in letters)
    {
        List<int> setIndexes = Enumerable.Range(0, sets.Count)
        .Where(i => row.Any(ch => sets[i].Contains(ch))).ToList();

        CoalesceSets(sets, row, setIndexes);
    }

    foreach (HashSet<char> set in sets)
    {
        Console.WriteLine("{ " + string.Join(", ", set) + " }");
    }
}

private static void CoalesceSets(List<HashSet<char>> sets, char[] row, List<int> setIndexes)
{
    if (setIndexes.Count == 0)
    {
        sets.Add(new HashSet<char>(row));
    }
    else
    {
        HashSet<char> targetSet = sets[setIndexes[0]];

        targetSet.UnionWith(row);

        for (int i = setIndexes.Count - 1; i >= 1; i--)
        {
            targetSet.UnionWith(sets[setIndexes[i]]);
            sets.RemoveAt(setIndexes[i]);
        }
    }
}
static void Main(字符串[]args)
{
字符[][]个字母=
{
新[]{A',B'},
新[]{C',D'},
新[]{'B','A','F'},
新[]{'I','F','J'},
};
列表集=新列表();
foreach(字符[]行,以字母表示)
{
List setIndexes=Enumerable.Range(0,sets.Count)
.Where(i=>row.Any(ch=>set[i].Contains(ch))).ToList();
合并集合(集合、行、集合索引);
}
foreach(HashSet-in-set)
{
Console.WriteLine(“{”+string.Join(“,”,set)+“}”);
}
}
私有静态void集合(列表集合、char[]行、列表集合索引)
{
if(setIndexes.Count==0)
{
添加(新哈希集(行));
}
其他的
{
HashSet targetSet=sets[setindex[0]];
targetSet.UnionWith(行);
对于(int i=setIndexes.Count-1;i>=1;i--)
{
UnionWith(集合[setIndexes[i]]);
sets.RemoveAt(setindex[i]);
}
}
}
它通过扫描先前标识的集合来建立输入数据集合,以找到当前数据行与哪些集合相交,然后将这些集合合并为包含所有成员的单个集合(您的规范似乎强加了传递成员身份…即,如果一个字母连接集合A和B,而另一个字母连接集合B和C,则您希望A、B和C都连接到一个集合中)

这不是一个最佳的解决方案,但它是可读的。您可以通过维护
字典来避免O(N^2)搜索,将每个字符映射到包含它的集合。然后不扫描所有集合,而是对当前行中的每个字符进行简单的查找,以建立集合索引列表。但是还有很多“内务管理”代码采用这种方法;除非您发现用更基本的方法实现时存在性能问题,否则我不会用这种方法来实现它



顺便说一句:我模糊地记得我以前在堆栈溢出上见过这种类型的问题,即这种集合的传递并集。我寻找了这个问题,但没有找到。你可能会更幸运,并且可能会发现关于这个问题及其答案还有其他有用的信息。

试图理解你的问题想出一个解决方案,我有几个问题。值从哪里来?在你的结果数据中,为什么“C”和“D”会与其他元素处于不同的组中?@cChacon这些值来自我的数据集,但它可以使用任何类型的值。一般来说,我需要根据数组中的元素与其他数组中的其他元素的相似性进行分组y、 “C”和“D”没有分组,因为字母[]中没有元素包含“C”和“D”。因此,首先,
A/B
B/A/F
组合在一起,生成
A/B/F
。然后它与
I/F/J
组合,生成
A/B/F/I/J
。组中没有重复的元素。
C/D
是唯一一个与其他数组元素没有相同字母(字母)的数组,因此它以不同的方式进行分组。然后,我建议您使用linq对数据集中的数据进行分组。通过使用linq,您可以对数据集进行分组,并使其在单个语句中返回字符串列表。您可以在此网站上找到许多示例。代码基本上如下所示:lstofstring=(来自dsChars group中的g,由x选择x)。ToList();它工作得非常好!非常感谢Peter先生!这就是我要找的!