Dan*_*ker 18 c# optimization linq-to-objects
更新 - 对于一个有思想的心态,你可以假设Aggregate仍会产生正常的结果,无论函数传递给它,包括在优化的情况下.
我编写了这个程序来构建一个从逗号分隔的0到19999之间的长整数字符串.
using System;
using System.Linq;
using System.Diagnostics;
namespace ConsoleApplication5
{
class Program
{
static void Main(string[] args)
{
const int size = 20000;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Enumerable.Range(0, size).Select(n => n.ToString()).Aggregate((a, b) => a + ", " + b);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms");
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,它说:
5116ms
Run Code Online (Sandbox Code Playgroud)
超过五秒钟,太可怕了.当然这是因为每次循环都会复制整个字符串.
但是,如果评论中指出了一个非常小的变化呢?
using System;
using System.Linq;
using System.Diagnostics;
namespace ConsoleApplication5
{
using MakeAggregateGoFaster; // <---- inserted this
class Program
{
static void Main(string[] args)
{
const int size = 20000;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
Enumerable.Range(0, size).Select(n => n.ToString()).Aggregate((a, b) => a + ", " + b);
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds + "ms");
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我运行它时,它说:
42ms
Run Code Online (Sandbox Code Playgroud)
超过100倍.
MakeAggregateGoFaster命名空间中有什么?
更新2: 在这里写下我的答案.
小智 44
为什么不使用其他形式的Aggregate?
Enumerable.Range(0, size ).Aggregate(new StringBuilder(),
(a, b) => a.Append(", " + b.ToString()),
(a) => a.Remove(0,2).ToString());
Run Code Online (Sandbox Code Playgroud)
您可以为种子指定任何类型,在第一个lambda函数中执行所需的任何格式化或自定义调用,然后在第二个lambda函数中自定义输出类型.内置功能已经提供了您所需的灵活性.我的跑步从1444ms到6ms.
mac*_*nir 15
您在命名空间MakeAggregateGoFaster中使用自己的扩展方法"覆盖"System.Linq.Aggregate.
也许专门研究IEnumerable<string>和使用StringBuilder?
也许采用一个Expression<Func<string, string, string>>而不是Func<string, string, string>它可以分析表达式树并编译一些使用StringBuilder而不是直接调用函数的代码?
只是猜测.
没有回答这个问题,但我认为这里的标准模式是使用StringBuilder或string.Join:
string.join(", ",Enumerable.Range(0, size).Select(n => n.ToString()).ToArray())
Run Code Online (Sandbox Code Playgroud)
我之所以问这是否是一个谜题,是因为只要满足所陈述问题的字面意义,谜题就可以不同程度地牺牲鲁棒性。考虑到这一点,这里是:
解决方案 1(立即运行,问题未验证):
public static string Aggregate(this IEnumerable<string> l, Func<string, string, string> f) {
return "";
}
Run Code Online (Sandbox Code Playgroud)
解决方案 2(运行速度与问题所需的速度差不多,但完全忽略委托):
public static string Aggregate(this IEnumerable<string> l, Func<string, string, string> f) {
StringBuilder sb = new StringBuilder();
foreach (string item in l)
sb.Append(", ").Append(item);
return sb.Remove(0,2).ToString();
}
Run Code Online (Sandbox Code Playgroud)