2

一个页面中有 5 个级联组合框,它们是动态创建的。当达到所需的总和时,我必须做一些事情。这是我生成一些输出的代码;我想动态生成所有的 for 循环,甚至所有的“cmb”数组。我怎样才能实现它?

private int[] cmb1 = { 0, 2, 4, 6, 8, 12, 16, 20 };
private int[] cmb2 = { 0, 2, 4, 6, 8, 12, 16, 20 };
private int[] cmb3 = { 0, 2, 4, 6, 8, 12, 16, 20 };
private int[] cmb4 = { 0, 2, 4, 6, 8, 12, 16, 20 };
private int[] cmb5 = { 0, 2, 4, 6, 8, 12, 16, 20 };
int count = 0;

        for (int i = 0; i < cmb1.Length; i++)
        {
            for (int j = 0; j < cmb2.Length; j++)
            {
                for (int k = 0; k < cmb3.Length; k++)
                {
                    for (int l = 0; l < cmb4.Length; l++)
                    {
                        for (int m = 0; m < cmb5.Length; m++)
                        {
                            if (cmb1[i] + cmb2[j] + cmb3[k] + cmb4[l] + cmb5[m] <= 20 && (i + j + k + l + m) != 0)
                            {
                                Console.WriteLine(count + " _ " + i + " " + j + " " + k + " " + l + " " + m);
                                count = count + 1;
                            }

                        }
                    }
                }
            }
        }
4

2 回答 2

3

您要执行的操作可以被视为未知(在编译时)数量的序列的笛卡尔积。

Eric Lippert 写了一篇关于如何在 C# 中创建这样一个解决方案的博客文章。他最终生成的代码是:

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 }));
}

使用它我们现在可以这样做:

List<int[]> cmbs = new List<int[]>();
cmbs.Add(new int[] { 0, 2, 4, 6, 8, 12, 16, 20 });
cmbs.Add(new int[] { 0, 2, 4, 6, 8, 12, 16, 20 });
cmbs.Add(new int[] { 0, 2, 4, 6, 8, 12, 16, 20 });

var query = cmbs.CartesianProduct()
    .Where(combo => combo.Sum() <= 20 && combo.Sum() > 0);

int count = 0;
foreach (var combo in query)
{
    Console.Write((count++) + " _ ");
    Console.WriteLine(string.Join(" ", combo));
}
于 2013-08-20T15:29:18.923 回答
1

我将带您阅读 Eric Lippert 关于在 Linq中实现笛卡尔积的优秀文章,他将其写为通用扩展方法

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
    // base case: 
    IEnumerable<IEnumerable<T>> result = new[] { Enumerable.Empty<T>() }; 
    foreach(var sequence in sequences) 
    { 
        var s = sequence; // don't close over the loop variable 
        // recursive case: use SelectMany to build the new product out of the old one 
        result = 
          from seq in result 
          from item in s 
          select seq.Concat(new[] {item}); 
    } 

    return result; 
}

因此,在您的代码中,您可以这样称呼它:

private List<int[]> cmbs = new List<int[]>();

...

// build cmbs list
cmbs.Add(cmb1);
cmbs.Add(cmb2);
cmbs.Add(cmb3);
cmbs.Add(cmb4);
cmbs.Add(cmb5);

// loop through cmbs
var count = 0;
foreach(var result in cmbs.CartesianProduct().Skip(1)) // Skip the first result
{
    if (result.Sum() <= 20) 
    {
        Console.WriteLine(count + "_" + String.Join(" ", result));
        count = count + 1;
    }
}
于 2013-08-20T15:29:07.487 回答