使用foreach循环</t>加入两个List <t>

时间:2013-01-07 15:54:21

标签: c# foreach

我试图稍微远离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 <-----

任何想法

  1. 为什么这比LINQ Join和
  2. 我怎样才能加快速度?
  3. 该程序显然可以满足需要,但速度太慢。

    编辑: 旧代码已满

    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;
            }
    

2 个答案:

答案 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)