生成集合内部集合的组合,而不与C#中当前集合的值相交

本文关键字:集合 前集 内部 组合 | 更新日期: 2023-09-27 18:30:01

在不与当前集(同一组中的项)的值相交的情况下,在其他集(组)内生成集(项集)的组合的好方法(易读且运行时快)是什么?

例如,我有两个简单的类。包含一组项目的组

public class Group
{
    public string Name { get; set; }
    public ISet<Item> Items { get; set; }
}
public class Item
{
    public string Name { get; set; }
}

因此,我有了一组组,每个组都包含一组项目,配置如下:

var groupA = new Group
{
    Name = "A",
    Items = new HashSet<Item> { 
        new Item { Name = "A1" }, 
        new Item { Name = "A2" }, 
        new Item { Name = "A3" } 
    }
};
var groupB = new Group
{
    Name = "B",
    Items = new HashSet<Item> { 
        new Item { Name = "B1" }, 
        new Item { Name = "B2" }, 
    }
};
var groupC = new Group
{
    Name = "C",
    Items = new HashSet<Item> { 
        new Item { Name = "C1" }, 
        new Item { Name = "C2" }, 
        new Item { Name = "C3" }, 
        new Item { Name = "C4" }, 
    }
};
var groupsSet = new HashSet<Group>();
groupsSet.Add(groupA);
groupsSet.Add(groupB);
groupsSet.Add(groupC);

groupsSet组合(如(1)和(2))中获得的好方法是什么

1)

A1, B1, C1
A1, B1, C2
A1, B1, C3
A1, B1, C4
A1, B2, C1
A1, B2, C2
A1, B2, C3
A1, B2, C4
A2, B1, C1
A2, B1, C2
A2, B1, C3
A2, B1, C4
A2, B2, C1
A2, B2, C2
A2, B2, C3
A2, B2, C4
A3, B1, C1
A3, B1, C2
A3, B1, C3
A3, B1, C4
A3, B2, C1
A3, B2, C2
A3, B2, C3
A3, B2, C4

2)

A1
A2
A3
B1
B2
C1
C2
C3
C4
A1, B1
A1, B2
A2, B1
A2, B2
A3, B1
A3, B2
A1, C1
A1, C2
A1, C3
A1, C4
A2, C1
A2, C2
A2, C3
A2, C4
A3, C1
A3, C2
A3, C3
A3, C4
B1, C1
B1, C2
B1, C3
B1, C4
B2, C1
B2, C2
B2, C3
B2, C4
A1, B1, C1
A1, B1, C2
A1, B1, C3
A1, B1, C4
A1, B2, C1
A1, B2, C2
A1, B2, C3
A1, B2, C4
A2, B1, C1
A2, B1, C2
A2, B1, C3
A2, B1, C4
A2, B2, C1
A2, B2, C2
A2, B2, C3
A2, B2, C4
A3, B1, C1
A3, B1, C2
A3, B1, C3
A3, B1, C4
A3, B2, C1
A3, B2, C2
A3, B2, C3
A3, B2, C4

当来自同一组的项目彼此不相交时,是否仅与其他组的项目相交?

组的数量和组中项目的数量可能不同。

组合中项目的顺序不相关。

谢谢。

生成集合内部集合的组合,而不与C#中当前集合的值相交

您正在寻找笛卡尔乘积,它可以简单地使用LINQ的SelectMany生成,或者在查询语法中生成:

var query = from a in groupA.Items
            from b in groupB.Items
            from c in groupC.Items
            select new Group()
            {
                Items = new HashSet<Item>() { a, b, c },
            };

var groupsSet = new HashSet<Group>(query);

如果你在编译时不知道组的数量,你可以使用Eric Lippert的这个解决方案来获得未知数量序列的笛卡尔乘积:

public static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
    IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
    return sequences.Aggregate(
        emptyProduct,
        (accumulator, sequence) =>
        from accseq in accumulator
        from item in sequence
        select accseq.Concat(new[] { item }));
}

它允许你写:

var groups = new[] { groupA.Items, groupB.Items, groupC.Items };
var query2 = groups.CartesianProduct()
    .Select(combination => new Group
    {
        Items = new HashSet<Item>(combination),
    });

您只是在寻找笛卡尔乘积吗?

你可以尝试这样的加入:

var product = 
    (from first in groupA 
    from second in groupB 
    from third in groupC             
    select new Group()
        {
            Items = new HashSet<Item>() { a, b, c },
        });