在c#中生成特定组合,创建我的预期输出

时间:2017-09-13 13:56:27

标签: c#

我有两个列表,每个列表中有多个数据。并且需要低于输出,这将是list(s)的组合值。

Example1:
List1: {"A","B","C"}
List2: {"D","E"}

Expected Output Combinations:
{"A"}
{"B"}
{"C"}
{"D"}
{"E"}
{"A,D"}
{"A,E"} 
{"B,D"}
{"B,E"}
{"C,D"}
{"C,E"}

Example2:
List1: {"A","B"}
List2: {"D"}

Expected Output Combinations:
{"A"}
{"B"}
{"D"}
{"A,D"}
{"B,D"}

以下是我正在尝试的代码段:

public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> source, int n)
{
    if (n == 0) yield return Enumerable.Empty<T>();

    int count = 1; 
    foreach (T item in source)
    {
        foreach (var innerSequence in source.Skip(count).Combinations(n - 1)) 
        {
            yield return new T[] { item }.Concat(innerSequence);}count++;
        } 
    }
}

public static IEnumerable<IEnumerable<T>> AllCombinations<T>(this IList<T> source)
{
    IEnumerable<IEnumerable<T>> output = Enumerable.Empty<IEnumerable<T>>(); 
    for (int i = 0; i < source.Count; i++)
    {
        output = output.Concat(source.Combinations(i));
    }
    return output;
}

...

List<string> lstCodes = new List<string>();
List<string> lstCodeOut = new List<string>();

if (!String.IsNullOrEmpty(txtbox1.Text))
    lstCodes.AddRange(txtbo‌​x1.Text.Split(',').T‌​oList());
if (!String.IsNullOrEmpty(txtbox2.Text))
    lstCodes.AddRange(txtbo‌​x2.Text.Split(',').T‌​oList());
if (!String.IsNullOrEmpty(txtbox3.Text))
    lstCodes.AddRange(txtbo‌​x3.Text.Split(',').T‌​oList());

foreach (var sequence in lstCodes.AllCombinations())
{
    lstCodeOut.Add(string.Join(",", sequence));
}
txtBox.Text = string.Join(Environment.NewLine, lstCodeOut);

1 个答案:

答案 0 :(得分:0)

最直接的方法是使用基本的foreach循环;假设没有重复:

var l1 = new List<string> { "A", "B", "C" };
var l2 = new List<string> { "D", "E" };

var result = new HashSet<string>();

foreach( string s1 in l1 )
{
    result.Add( s1 );

    foreach( string s2 in l2 )
    {
        result.Add( s2 );
        result.Add( $"{s1},{s2}" );
    }
}

从这里开始,我们可以通过连接2个列表然后将2合并到组合中来重构以消除内部循环中的一些冗余:

var l1 = new List<string> { "A", "B", "C" };
var l2 = new List<string> { "D", "E" };

var result = new List<string>( l1.Concat( l2 ) );

foreach( string s1 in l1 )
{
    foreach( string s2 in l2 )
    {
        result.Add( $"{s1},{s2}" );
    }
}

从这里开始,我们可以再次重构为LINQ语句:

var l1 = new List<string> { "A", "B", "C" };
var l2 = new List<string> { "D", "E" };

string[] result = l1
    .Concat( l2 )
    .Concat( l1.SelectMany( s1 => l2, ( s1, s2 ) => $"{s1},{s2}" ) )
    .ToArray();