Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从列表中选择不同数量的项目组合_C#_.net_For Loop - Fatal编程技术网

C# 从列表中选择不同数量的项目组合

C# 从列表中选择不同数量的项目组合,c#,.net,for-loop,C#,.net,For Loop,假设我有一个任意长度的整数列表,例如,我有一个1,3,5和7的列表 我想要一个从列表中选择X元素组合的算法 例如,X=1将返回: 一, 三, 五, 七, x=2将返回: 1+1 1+3 1+5 1+7 3+3 3+5 3+7 5+5 5+7 7+7 var listOfInts=新列表{1,3,5,7}; var combinedts=新列表(); //x=1溶液 //这只是从列表中选择一项。 对于(int i=0;ilistOfInts[x]).Sum()+”;“+tempSum); 组合项。

假设我有一个任意长度的整数列表,例如,我有一个1,3,5和7的列表

我想要一个从列表中选择X元素组合的算法

例如,X=1将返回:

一,

三,

五,

七,

x=2将返回:

1+1

1+3

1+5

1+7

3+3

3+5

3+7

5+5

5+7

7+7

var listOfInts=新列表{1,3,5,7};
var combinedts=新列表();
//x=1溶液
//这只是从列表中选择一项。
对于(int i=0;i
这个解决方案不能扩展,因为我必须为我选择的每个元素的数量不断地环绕另一个for循环。例如,X=7需要7个嵌套的For循环。有没有更好的方法来编写这种不涉及循环嵌套的方法?

这对我很有用:

Func<IEnumerable<int>, int, IEnumerable<IEnumerable<int>>> generate = null;
generate = (xs, n) =>
    (xs == null || !xs.Any())
        ? Enumerable.Empty<IEnumerable<int>>()
        : n == 1
            ? xs.Select(x => new [] { x })
            : xs.SelectMany(x => generate(xs, n - 1).Select(ys => ys.Concat(new [] { x })));

int[] array = { 1, 3, 5, 7, };

var results =
    generate(array, 3)
        .Select(xs => String.Join("+", xs));
Func generate=null;
生成=(xs,n)=>
(xs==null | |!xs.Any())
? Enumerable.Empty()
:n==1
? 选择(x=>new[]{x})
:xs.SelectMany(x=>generate(xs,n-1).Select(ys=>ys.Concat(new[]{x}));
int[]数组={1,3,5,7,};
var结果=
生成(数组,3)
.Select(xs=>String.Join(“+”,xs));
通过这个电话,我得到:

1+3+1、3+3+1+1+1+1、3+3+1、5+3+1、5+3+1、5+3+1、5+3+1、7+3+3+1、1+3+1、1+3+1、1+1+1、1+1+1+1、1+1+1+1+1、3+1+1、5+1+1+1、5+1+1、7+3+1、1+1、1+1+1、7+3+1、1+1、1+1、1、1+1+1、1+1+1、1+1、1+1、1+1+1、1、1+1+1+1、1、1+1+1、1+1+1、1、1+3+1、1+3+1、1、1+1+1+1+1、1+1+1、1、1、1+1、1+1、1+1 3,1+1+5,3+1+5,5+1+5,7+1+5,1+3+5,3+3+5,5+3+5,7+3+5,1+5+5,3+5+5,5+5+5,7+5,1+7+5,3+7+5,5+7+5,1+1+7,3+1+7、5+1+7、7+1+7、1+3+7、3+3+7、5+3+7、7+3+7、1+5+7、3+5+7、5+5+7、7+5+7、1+7+7、3+7+7、5+7+7、7+7+7


您可以使用以下方法获得序列的组合:

public static class LinqHelper
{
    public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int? k = null)
    {
        if (!k.HasValue)
            k = elements.Count();

        return k == 0 ? new[] { new T[0] } :
           elements.SelectMany((e, i) => elements.Skip(i).Combinations(k - 1).Select(c => (new[] { e }).Concat(c)));
    }
}

var list = new List<int> { 1, 3, 5, 7 };

int x = 2; //Change to 3, 4, 5, etc

var result = list.Combinations(x);
产生:

2
4
6
8
6
8
10
10
12
十四,


还有一种纯粹的迭代方法可以做到这一点。它需要更多的思考和复杂性,但可以非常有效。基本思想是模拟相同的嵌套循环,但将每个嵌套循环的迭代作为循环计数器数组进行跟踪,循环计数器以与原始嵌套循环代码相同的方式向前迭代。以下是一个完全有效的示例:

var listOfInts = new List<int> { 1, 3, 5, 7 };
var combinedInts = new List<int>();

var numInts = listOfInts.Count;
var numElements = 5; // number of "nested loops", or ints selected in each combination
var loopCounters = new int[numElements]; // make one loop counter for each "nested loop"
var lastCounter = numElements - 1; // iterate the right-most counter by default

// maintain current sum in a variable for efficiency, since most of the time
// it is changing only by the value of one loop counter change.
var tempSum = listOfInts[0] * numElements;

// we are finished when the left/outer-most counter has looped past number of ints
while (loopCounters[0] < numInts) {
    // you can use this to verify the output is iterating correctly:
    // Console.WriteLine(string.Join(",", loopCounters.Select(x => listOfInts[x])) + ": " + loopCounters.Select(x => listOfInts[x]).Sum() + "; " + tempSum);

    combinedInts.Add(tempSum);

    tempSum -= listOfInts[loopCounters[lastCounter]];
    loopCounters[lastCounter]++;
    if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];

    // if last element reached in inner-most counter, increment previous counter(s).
    while (lastCounter > 0 && loopCounters[lastCounter] == numInts) {
        lastCounter--;
        tempSum -= listOfInts[loopCounters[lastCounter]];
        loopCounters[lastCounter]++;
        if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
    }

    // if a previous counter was advanced, reset all future counters to same
    // starting number to start iteration forward again.
    while (lastCounter < numElements - 1) {
        lastCounter++;
        if (loopCounters[lastCounter] < numInts) tempSum -= listOfInts[loopCounters[lastCounter]];
        loopCounters[lastCounter] = loopCounters[lastCounter - 1];
        if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
    }
}
var listOfInts=新列表{1,3,5,7};
var combinedts=新列表();
var numInts=listofits.Count;
变量numElements=5;//在每个组合中选择的“嵌套循环”或整数的数量
var loopCounters=新整数[numElements];//为每个“嵌套循环”制作一个循环计数器
var lastCounter=numElements-1;//默认情况下,迭代最右边的计数器
//在变量中保持当前总和以提高效率,因为大多数情况下
//它仅通过一个循环计数器的值改变。
var tempSum=listOfInts[0]*numElements;
//当最左边/最外面的计数器循环超过整数时,我们就结束了
while(循环计数器[0]listOfInts[x]))+”:“+loopCounters.Select(x=>listOfInts[x]).Sum()+”;“+tempSum);
组合项。添加(tempSum);
tempSum-=listOfInts[loopCounters[lastCounter]];
循环计数器[最后一个计数器]+;
if(loopCounters[lastCounter]0&&loopCounters[lastCounter]==numInts){
最后计数器--;
tempSum-=listOfInts[loopCounters[lastCounter]];
循环计数器[最后一个计数器]+;
if(loopCounters[lastCounter]

在迭代结束时,
combinedts
应包含所有和组合的列表,类似于原始代码或其他递归解决方案。如果您使用的是小集合和小组合,那么这种级别的效率是不必要的,您应该更喜欢递归解决方案,它更容易对正确性进行推理。我将此作为思考问题的另一种方式。干杯

您希望递归调用单循环的函数。例如递归,请看这实际上应该是的一个副本-您正在寻找x个列表的笛卡尔乘积。要得到总数,您只需将其相加。@Rob您是对的-我选错了一个(在您注释:)时重新打开)。请注意,“选择一个可变的数字”可能意味着,但sample确实谈到了笛卡尔积。@layric,作为递归的一个例子,实际上我不相信建议的重复回答了这个问题。
var result = list.Combinations(x).Select(g => g.Aggregate((left, right) => left + right));
var listOfInts = new List<int> { 1, 3, 5, 7 };
var combinedInts = new List<int>();

var numInts = listOfInts.Count;
var numElements = 5; // number of "nested loops", or ints selected in each combination
var loopCounters = new int[numElements]; // make one loop counter for each "nested loop"
var lastCounter = numElements - 1; // iterate the right-most counter by default

// maintain current sum in a variable for efficiency, since most of the time
// it is changing only by the value of one loop counter change.
var tempSum = listOfInts[0] * numElements;

// we are finished when the left/outer-most counter has looped past number of ints
while (loopCounters[0] < numInts) {
    // you can use this to verify the output is iterating correctly:
    // Console.WriteLine(string.Join(",", loopCounters.Select(x => listOfInts[x])) + ": " + loopCounters.Select(x => listOfInts[x]).Sum() + "; " + tempSum);

    combinedInts.Add(tempSum);

    tempSum -= listOfInts[loopCounters[lastCounter]];
    loopCounters[lastCounter]++;
    if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];

    // if last element reached in inner-most counter, increment previous counter(s).
    while (lastCounter > 0 && loopCounters[lastCounter] == numInts) {
        lastCounter--;
        tempSum -= listOfInts[loopCounters[lastCounter]];
        loopCounters[lastCounter]++;
        if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
    }

    // if a previous counter was advanced, reset all future counters to same
    // starting number to start iteration forward again.
    while (lastCounter < numElements - 1) {
        lastCounter++;
        if (loopCounters[lastCounter] < numInts) tempSum -= listOfInts[loopCounters[lastCounter]];
        loopCounters[lastCounter] = loopCounters[lastCounter - 1];
        if (loopCounters[lastCounter] < numInts) tempSum += listOfInts[loopCounters[lastCounter]];
    }
}