如何使用UNION对char / string数组进行分组?

时间:2016-05-01 05:26:16

标签: c# arrays linq grouping union

我有一个二维char数组,叫做Letters [] []

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或者只是标准的阵列访问。

我该如何以最佳方式对其进行分组?或者还有其他解决方案吗?

1 个答案:

答案 0 :(得分:1)

我认为纯粹的LINQ解决方案会过于复杂。这不是一个简单的联合操作(如果我理解你的规范)。你想基于非空交叉点进行联合。这意味着必须首先重新排列数据,以便LINQ可以进行连接,找到匹配的数据,并且由于LINQ只会加入相等,这样做,同时保留原始分组信息将导致语法更多麻烦比它值得,恕我直言。

这是一个非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]);
        }
    }
}

它通过扫描先前识别的集合来构建输入数据集,以查找当前数据行与哪些集合相交,然后将这些集合合并为包含所有成员的单个集合(您的规范似乎强加了传递成员资格...即如果一个字母加入集合A和B,并且另一个字母加入集合B和C,则希望A,B和C都加入到单个集合中。

这不是最佳解决方案,但它具有可读性。您可以通过维护Dictionary<char, int>来将每个字符映射到包含它的集合来避免O(N ^ 2)搜索。然后,不是扫描所有集合,而是对当前行中的每个字符进行简单查找,以构建集合索引列表。但是还有很多&#34;内务管理&#34;代码采用这种方法;除非你找到一个经过验证的性能问题,否则我不会那么费心地实现它。


顺便说一句:我有一个模糊的回忆我之前在Stack Overflow上看过这种类型的问题,即这种集合的传递联合。我找了问题,但找不到。您可能会有更多的运气,并且可能会发现该问题及其答案还有其他有用的信息。