繁体   English   中英

再说一次,如何在 C# 中处理庞大的集合

[英]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.ForEachwhile(partition.MoveNext())和更改集合类型。 即使partition.Count()需要数年才能执行。

我知道一种解决方法。 计算可以放在SplitAppends方法内部并在堆栈的顶层执行,但这种方式似乎很棘手。

所以我发现了问题。 在调用该方法时,'yield' 没有给我任何结果。 只有当我使用屈服元素时。 这就是为什么这个方法在 1 毫秒内完成,而 'foreach' 需要这么长时间。 并且问题有~O(2^N) 难度,这就是为什么我们不能使用 if for N=360。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM