用LINQ替换foreach
我有一些非常简单的代码,我正在尝试使用LINQ而不是标准代码以稍微快一点的速度运行(代码中有很多这样的小类型的调用,这似乎会减慢速度) 问题是,我在LINQ之外有一个变量,LINQ查询的结果需要添加它 原始代码如下所示用LINQ替换foreach,linq,c#-4.0,Linq,C# 4.0,我有一些非常简单的代码,我正在尝试使用LINQ而不是标准代码以稍微快一点的速度运行(代码中有很多这样的小类型的调用,这似乎会减慢速度) 问题是,我在LINQ之外有一个变量,LINQ查询的结果需要添加它 原始代码如下所示 double total = 0 foreach(Crop c in p.Crops) { if (c.CropType.Type == t.Type) total += c.Area; } return total; 这种方法在循环开始变大之前不会变慢,
double total = 0
foreach(Crop c in p.Crops)
{
if (c.CropType.Type == t.Type)
total += c.Area;
}
return total;
这种方法在循环开始变大之前不会变慢,然后在手机上变慢。这类代码可以移动到一个相对快速和简单的LINQ吗?看起来您可以使用sum:(编辑:我的语法错了) 或以扩展方法格式:
total = p.Crops.Where(c => c.CropType.Type == t.Type).Sum(c => c.area);
至于有人说LINQ不会表现得更好你的证据呢?(以下内容基于?我在linqpad中运行了以下内容:(您需要下载并引用它才能运行)
void Main()
{
//Nbuilder用于创建样本数据块
//http://nbuilder.org
var crops=Builder.CreateListOfSize(1000000.Build();
var t=新作物();
t、 Type=Type.grain;
双倍合计=0;
var sw=新秒表();
sw.Start();
foreach(作物中的作物c)
{
if(c.Type==t.Type)
总面积+=c.面积;
}
sw.Stop();
total.Dump(“For循环总计:”);
sw.elapsedmillesons.Dump(“对于循环经过的时间:”);
sw.Restart();
var结果=作物。其中(c=>c.Type==t.Type)。总和(c=>c.area);
sw.Stop();
结果.转储(“LINQ总计:”);
sw.elapsedmillesons.Dump(“LINQ运行时间:”);
sw.Restart();
var result2=(来自作物中的c)
其中c.Type==t.Type
选择c.area).Sum();
Dump(“LINQ(sugar语法)total:”;
sw.elapsedmillesons.Dump(“LINQ(糖语法)运行时间:”);
}
公共枚举类型
{
小麦
粮食
玉米
玉米
棉
}
公营作物
{
公共字符串名称{get;set;}
公共类型类型{get;set;}
公共双区;
}
结果对LINQ有利:
循环总计:99999900000
循环运行时间:25
LINQ总计:99999900000
LINQ运行时间:17
LINQ(糖语法)总计:99999900000
LINQ(糖语法)运行时间:17
看起来您可以使用sum:(编辑:我的语法错误) 或以扩展方法格式:
total = p.Crops.Where(c => c.CropType.Type == t.Type).Sum(c => c.area);
至于有人说LINQ不会表现得更好,你的证据在哪里?(以下是基于?我在linqpad中运行了以下内容:(你需要下载并参考才能运行它)
void Main()
{
//Nbuilder用于创建样本数据块
//http://nbuilder.org
var crops=Builder.CreateListOfSize(1000000.Build();
var t=新作物();
t、 Type=Type.grain;
双倍合计=0;
var sw=新秒表();
sw.Start();
foreach(作物中的作物c)
{
if(c.Type==t.Type)
总面积+=c.面积;
}
sw.Stop();
total.Dump(“For循环总计:”);
sw.elapsedmillesons.Dump(“对于循环经过的时间:”);
sw.Restart();
var结果=作物。其中(c=>c.Type==t.Type)。总和(c=>c.area);
sw.Stop();
结果.转储(“LINQ总计:”);
sw.elapsedmillesons.Dump(“LINQ运行时间:”);
sw.Restart();
var result2=(来自作物中的c)
其中c.Type==t.Type
选择c.area).Sum();
Dump(“LINQ(sugar语法)total:”;
sw.elapsedmillesons.Dump(“LINQ(糖语法)运行时间:”);
}
公共枚举类型
{
小麦
粮食
玉米
玉米
棉
}
公营作物
{
公共字符串名称{get;set;}
公共类型类型{get;set;}
公共双区;
}
结果对LINQ有利:
循环总计:99999900000
循环运行时间:25
LINQ总计:99999900000
LINQ运行时间:17
LINQ(糖语法)总计:99999900000
LINQ(糖语法)运行时间:17
优化这一点的主要方法是改变
p
,这可能是可能的,也可能是不可能的
假设p
是p
,如下所示:
internal sealed class P
{
private readonly List<Crop> mCrops = new List<Crop>();
public IEnumerable<Crop> Crops { get { return mCrops; } }
public void Add(Crop pCrop)
{
mCrops.Add(pCrop);
}
}
然后,您的代码会变成:
double total = 0
foreach(Crop crop in p.GetCropsByType(t.Type))
total += crop.Area;
return total;
另一种更快的可能性是:
internal sealed class P
{
private readonly List<Crop> mCrops = new List<Crop>();
private double mTotalArea;
public IEnumerable<Crop> Crops { get { return mCrops; } }
public double TotalArea { get { return mTotalArea; } }
public void Add(Crop pCrop)
{
mCrops.Add(pCrop);
mTotalArea += pCrop.Area;
}
}
您也可以考虑将代码< >庄稼> /代码>数据的代码提取到一个单独的类,这取决于什么是<代码> p>代码> .p/> 。优化这个的主要方式将改变<代码> p>代码>,这可能或不可能。
假设p
是p
,如下所示:
internal sealed class P
{
private readonly List<Crop> mCrops = new List<Crop>();
public IEnumerable<Crop> Crops { get { return mCrops; } }
public void Add(Crop pCrop)
{
mCrops.Add(pCrop);
}
}
然后,您的代码会变成:
double total = 0
foreach(Crop crop in p.GetCropsByType(t.Type))
total += crop.Area;
return total;
另一种更快的可能性是:
internal sealed class P
{
private readonly List<Crop> mCrops = new List<Crop>();
private double mTotalArea;
public IEnumerable<Crop> Crops { get { return mCrops; } }
public double TotalArea { get { return mTotalArea; } }
public void Add(Crop pCrop)
{
mCrops.Add(pCrop);
mTotalArea += pCrop.Area;
}
}
您也可以考虑将代码< >庄稼> /代码>数据的代码提取到一个单独的类,这取决于什么是<代码> p>代码> .< /p> < p>这是一个非常直接的和,所以我怀疑您会从使用LINQ .< 关于这里的设置,您没有告诉我们太多,但这里有一个想法。如果
p.Crops
很大,并且序列中只有少量的项目是所需的类型,您可以构建另一个序列,其中只包含您需要的项目
我假设您在插入
p.Crops
时知道类型。如果是这种情况,您可以轻松地在另一个集合中插入相关项,并将其用于求和循环。这将减少N并消除比较。它仍然是O(N)尽管如此。这是一个相当直接的总数,所以我怀疑您是否会从使用LINQ中看到任何好处
关于这里的设置,您没有告诉我们太多,但这里有一个想法。如果p.Crops
很大,并且序列中只有少量的项目是所需的类型,您可以构建另一个序列,其中只包含您需要的项目
我假设您在插入p.Crops
时知道类型