我试图稍微远离LINQ,这已被证明非常有用,但有时也很难阅读。
我曾经使用LINQ来执行连接(完全外部连接),但是为了简单起见,我们更喜欢使用for / foreach循环。我刚刚将一个LINQ语句(不是PLINQ)转换为嵌套的foreach循环,性能受到了严重影响。过去需要几秒钟的时间现在需要大约一分钟,请参阅下面的代码。
foreach (var p in PortfolioELT)
{
double meanloss;
double expvalue;
double stddevc;
double stddevi;
bool matched = false;
foreach (var a in AccountELT)
{
if (a.eventid == p.eventid)
{ DO SOME MATH HERE <-----
任何想法
该程序显然可以满足需要,但速度太慢。
编辑: 旧代码已满
public static ConcurrentList<Event> CreateNewELTSUB(IList<Event> AccountELT, IList<Event> PortfolioELT)
{
if (AccountELT == null)
{
return (ConcurrentList<Event>)PortfolioELT;
}
else
{
//Subtract the Account ELT from the Portfolio ELT
var newELT = from p in PortfolioELT
join a in AccountELT
on p.eventid equals a.eventid into g
from e in g.DefaultIfEmpty()
select new
{
EventID = p.eventid,
Rate = p.rate,
meanloss = p.meanloss - (e == null ? 0d : e.meanloss),
expValue = p.expValue - (e == null ? 0d : e.expValue),
stddevc = Math.Sqrt(Math.Pow(p.stddevc, 2) - (e == null ? 0d : Math.Pow(e.stddevc, 2))),
stddevi = Math.Sqrt(Math.Pow(p.stddevi, 2) - (e == null ? 0d : Math.Pow(e.stddevi, 2)))
};
ConcurrentList<Event> list = new ConcurrentList<Event>();
foreach (var x in newELT)
{
list.Add(new Event(x.meanloss, x.EventID, x.expValue, x.Rate, x.stddevc, x.stddevi));
}
return list;
}
}
新代码已满:
public static ConcurrentList<Event> CreateNewELTSUB(IList<Event> AccountELT, IList<Event> PortfolioELT)
{
if (AccountELT == null)
{
return (ConcurrentList<Event>)PortfolioELT;
}
else
{
//Subtract the Account ELT from the Portfolio ELT
ConcurrentList<Event> newlist = new ConcurrentList<Event>();
//Outer Join on Portfolio ELT
foreach (var p in PortfolioELT)
{
double meanloss;
double expvalue;
double stddevc;
double stddevi;
bool matched = false;
foreach (var a in AccountELT)
{
if (a.eventid == p.eventid)
{
matched = true;
meanloss = p.meanloss - a.meanloss;
expvalue = p.expValue - a.expValue;
stddevc = Math.Sqrt((Math.Pow(p.stddevc, 2)) - (Math.Pow(a.stddevc, 2)));
stddevi = Math.Sqrt((Math.Pow(p.stddevi, 2)) - (Math.Pow(a.stddevi, 2)));
newlist.Add(new Event(meanloss, p.eventid, expvalue, p.rate, stddevc, stddevi));
}
else if (a.eventid != p.eventid) //Outer Join on Account
{
newlist.Add(a);
}
}
if (!matched)
{
newlist.Add(p);
}
}
return newlist;
}
答案 0 :(得分:6)
为什么这比LINQ Join和
慢
我正在跳过故意回答
如何加快速度?
您为每个AccountELT
循环遍历整个PortfolioELT
集合。你应该循环一个,并让另一个转换为一个字典,以便更容易找到一个特定的记录。类似的东西:
var accountELTIdx = AccountELT.ToDictionary(k => k.eventid);
然后
foreach (var p in PortfolioELT)
{
double meanloss;
double expvalue;
double stddevc;
double stddevi;
bool matched = false;
if(accountELTIdx.ContainsKey(p.eventid)
{
var acct = accountELTIdx[p.eventid];
// some maths
}
....
答案 1 :(得分:2)
您每次迭代都会创建局部变量,可能会也可能不会使用。
double meanloss;
double expvalue;
double stddevc;
double stddevi;
bool matched = false;
您正在对匹配事件ID进行线性搜索,如果只有一个列表按“eventid”排序,则可以使用二分搜索而不是完全线性搜索的浪费。
foreach (var a in AccountELT)
{
if (a.eventid == p.eventid)