考虑一个简单的方程:5 = 2 * a + 4 * b-3 * c
通过变量循环比使用多个for循环更好吗?
这有多个答案,但是为了找到方程式的答案,我使用了多个for循环,例如
for(int a = 1; a < 50; a++) {
for(int b = 1; b < 50; b++) {
for(int c = 1; c < 50; c++) {
//validate
}
}
}
现在,对于此示例,这将不需要太多时间。但是,如果这要经过成千上万个条目的数据集,并且for循环的目标是看到,如果我可以找到一组优化的变量,那么它将花费一些时间。也许有3个以上。上面的方程只是一个例子。
是否有另一种更好的方法?可能是代码模式?我也很想看看我如何清理它,因为有很多嵌套。
我的验证逻辑已经被扔到BackgroundWorker中,并且我限制了计数,因此我可以利用100%的CPU,因此我主要考虑的是尽可能不进行for循环嵌套。
答案 0 :(得分:1)
嵌套循环是最有效的方法,您可以通过Parallel.For
设置外部循环很容易地并行化它。
int solutionsCount = 0;
Parallel.For(1, 50, a =>
{
for (int b = 1; b < 50; b++)
for (int c = 1; c < 50; c++)
if (2 * a + 4 * b - 3 * c == 0) Interlocked.Increment(ref solutionsCount);
});
如果想花哨的话,可以创建一个自定义迭代器,该迭代器将产生所有排列:
private static IEnumerable<(int a, int b, int c)> Loop(int to1, int to2, int to3)
{
for (int a = 1; a < to1; a++)
for (int b = 1; b < to2; b++)
for (int c = 1; c < to3; c++)
yield return (a, b, c); // this is a ValueTuple<int, int, int>
}
并像这样使用它:
foreach (var p in Loop(50, 50, 50))
{
// Do something with p.a, p.b and p.c
}
您甚至可以使用LINQ直接获得解决方案:
var solutions = Loop(50, 50, 50)
.Where(p => 2 * p.a + 4 * p.b - 3 * p.c == 0);
Console.WriteLine($"Solutions: {String.Join(", ", solutions)}");
...但是速度要慢10倍。
您甚至可以像这样使用纯LINQ:
var solutions = Enumerable.Range(1, 50 - 1)
.SelectMany(a => Enumerable.Range(1, 50 - 1)
.SelectMany(b => Enumerable.Range(1, 50 - 1)
.Where(c => 2 * a + 4 * b - 3 * c == 0)));
...具有与上一个相同的性能。通过在查询中链接AsParallel()
(在第一个Enumerable.Range
之后),它也可以并行化。