[英]And again, how to handle a huge collection in C#
我的“任务”的第一部分是找到一个数字(在我的例子中是 365)的所有加数(分区)以及这些序列的所有可能排列。
例如:对于数字 3,我们有三个可能的加数序列 (3) (1;2) (1;1;1) 但我的方法给出 (3) (1;2) (2;1) (1;1;1) ),因为我需要。
IEnumerable<int[]> SplitAddends(int n) {
for (int i = 1; i < n; i++) {
var part = SplitAddends(n - i);
foreach (var array in part) {
var newArray = new int[array.Length + 1];
newArray[0] = i;
Array.Copy(array, 0, newArray, 1, array.Length);
yield return newArray;
}
}
yield return new []{n};
}
这种方法在不到 1 毫秒的时间内给出结果,它是正确的。 问题是这个任务的第二部分。 我需要对每个元素进行一些计算。 例如:
void ExampleMethod(int N) {
var partition = SplitAddends(N); // < 1ms execution time
foreach (var variant in partition) { // problematic line
var someResult = 0f;
foreach (var item in variant) {
someResult += SomeEquation(item);
}
SendToCompare(someResult);
}
}
像 15-25 这样的数字需要几秒钟(对于 N=20 分区有 524288 个序列),像 35-50 这样的数字需要几个小时。
我已经尝试过Parallel.ForEach
, while(partition.MoveNext())
和更改集合类型。 即使partition.Count()
需要数年才能执行。
我知道一种解决方法。 计算可以放在SplitAppends
方法内部并在堆栈的顶层执行,但这种方式似乎很棘手。
所以我发现了问题。 在调用该方法时,'yield' 没有给我任何结果。 只有当我使用屈服元素时。 这就是为什么这个方法在 1 毫秒内完成,而 'foreach' 需要这么长时间。 并且问题有~O(2^N) 难度,这就是为什么我们不能使用 if for N=360。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.