多个列表的组合

时间:2012-09-18 08:57:05

标签: c# combinations

我不完全确定“组合”这个词是正确的,但是我需要构建一个或多个List的组合列表。每个列表将包含不同数量的元素,例如

List<string> lBag1 = ["1_0, 1_1, 1_3"]
List<string> lBag2 = ["11_0, 11_1, 11_8"]
List<string> lBag3 = ["3_0"]

我需要的是列表的所有组合形式1到n个元素,每个列表不超过一个元素,例如

"1_0"
"1_1"
"1_3"
"11_0"
"11_1"
"11_8"
"3_0"
"1_0 11_0"
"1_0 11_1"
"1_0 11_8"
"1_0 3_0"
...
"1_3 11_8 3_0"

顺序并不重要,因此“1_0 11_0”被认为与“11_0 1_0”相同。

非常感谢任何帮助

3 个答案:

答案 0 :(得分:1)

这适合你吗?

var empty = new string[] { null, };

var query =
    from b1 in empty.Concat(lBag1)
    from b2 in empty.Concat(lBag2)
    from b3 in empty.Concat(lBag3)
    let bs = new [] { b1, b2, b3 }.Where(b => b != null)
    let result = String.Join(" ", bs)
    where result != ""
    select result;

答案 1 :(得分:1)

这两种扩展方法可以将几个枚举链接在一起,计算出你想要的组合。

每个组合都是枚举,而不是连接的字符串。

// This method takes two sequences of T, and returns
//  - each element of the first sequence,
//        wrapped in its own one-element sequence
//  - each element of the second sequence,
//        wrapped in its own one-element sequence
//  - each pair of elements (one from each sequence),
//        as a two-element sequence.
// e.g. { 1 }.CrossWith({ 2 }) returns { { 1 }, { 2 }, { 1, 2 } }
public static IEnumerable<IEnumerable<T>> CrossWith<T>(
    this IEnumerable<T> source1,
    IEnumerable<T> source2)
{
    foreach(T s1 in source1) yield return new[] { s1 };
    foreach(T s2 in source2) yield return new[] { s2 };
    foreach(T s1 in source1)
        foreach(T s2 in source2)
            yield return new[] { s1, s2 };
}

// This method takes a sequence of sequences of T and a sequence of T,
//     and returns
//  - each sequence from the first sequence
//  - each element of the second sequence,
//        wrapped in its own one-element sequence
//  - each pair, with the element from the second sequence appended to the
//        sequence from the first sequence.
// e.g. { { 1, 2 } }.CrossWith({ 3 }) returns
//      { { 1, 2 }, { 3 }, { 1, 2, 3 } }
public static IEnumerable<IEnumerable<T>> CrossWith<T>(
    this IEnumerable<IEnumerable<T>> source1,
    IEnumerable<T> source2)
{
    foreach(IEnumerable<T> s1 in source1) yield return s1;
    foreach(T s2 in source2) yield return new[] { s2 };
    foreach(IEnumerable<T> s1 in source1)
        foreach(T s2 in source2)
            yield return s1.Concat(new[] { s2 }).ToArray();
}

var cross = lBag1.CrossWith(lBag2).CrossWith(lBag3);
// { "1_0" }, { "1_1" }, { "1_3" } ...
// ... { "1_0", "11_0" }, ...

或者,有this classic Eric Lippert博客帖子做类似的事情。 (类似的结果,非常不同的方法。)

答案 2 :(得分:0)

这只是我的意见。你必须自己决定如何实现它,但我会:

1)创建一个类来表示你的对X_Y

2)让你的类实现IEquatable

3)提供Equal

的实现

4)实现一个构造函数,给定X_Y形式的字符串返回一个YourClass对象。

5)实现一个公共静态函数,给定一个包含逗号的字符串,分隔X_Y列表返回一个List

6)使用前面的方法创建三个列表。

7)创建一个空列表

8)使用yourList.Append添加trhee列表中的元素。

可能是我用枪来杀苍蝇。