2012-12-29 47 views
1

我将如何写这与linq?我将如何优化LINQ的嵌套for循环

foreach (var to in allCurrentTradeObjects) 
{ 
    foreach (var ro in theseWantMe) 
    { 
     if (ro.Type != to.Type 
       || ro.MaxRent < to.Rent 
       || ro.MinRooms > to.Rooms 
       || ro.MinSquareMeters > to.SquareMeters 
       || ro.MaxPrice < to.Price 
       || ro.MinFloors > to.Floors 
       || ro.TradeObjectId == to.TradeObjectId 
       || ro.TradeObjectId == myTradeObject.TradeObjectId) 
     { 
      continue; 
     } 
     RatingListTriangleModel rlt = new RatingListTriangleModel 
     { 
      To1Id = myTradeObject.TradeObjectId, 
      To2Id = to.TradeObjectId, 
      To3Id = ro.TradeObjectId, 
      T1OnT2Rating = 0, 
      T2OnT3Rating = 0, 
      T3OnT1Rating = 0, 
      TotalRating = 0 
     }; 

     //_context.RatingListTriangle.Add(rlt); 
     this.InsertOrUpdate(rlt); 

    } 
} 
this.Save(); 
+0

优化是为了什么? –

回答

5
var query = from to in allCurrentTradeObjects 
      from ro in theseWantMe 
      where ro.Type == to.Type && 
        ro.MaxRent >= to.Rent && 
        ro.MinRooms <= to.Rooms && 
        ro.MinSquareMeters <= to.SquareMeters && 
        ro.MaxPrice >= to.Price && 
        ro.MinFloors <= to.Floors && 
        ro.TradeObjectId != to.TradeObjectId && 
        ro.TradeObjectId != myTradeObject.TradeObjectId 
      select new RatingListTriangleModel 
      { 
       To1Id = myTradeObject.TradeObjectId, 
       To2Id = to.TradeObjectId, 
       To3Id = ro.TradeObjectId, 
       T1OnT2Rating = 0, 
       T2OnT3Rating = 0, 
       T3OnT1Rating = 0, 
       TotalRating = 0 
      }; 

foreach(var rlt in query) 
    this.InsertOrUpdate(rlt); 

this.Save(); 
+0

让我们来看看linq吧。我的意思是这种方式更好。 :(:(:(+1反正 –

+2

@TonyHopkinson我想这是可读性优化.. –

+1

庵,可读性对我将是对构造的过载,并在RO和某种比较,虽然扭转了逻辑并摆脱该continue语句使代码100%可读性更强直客。我花了五分钟,甚至毫无察觉。 –

1

以下是方法的语法。

allCurrentTradeObjects.Select (
      to => to.theseWantMe.Where (ro => !(ro.Type != to.Type 
       || ro.MaxRent < to.Rent 
       || ro.MinRooms > to.Rooms 
       || ro.MinSquareMeters > to.SquareMeters 
       || ro.MaxPrice < to.Price 
       || ro.MinFloors > to.Floors 
       || ro.TradeObjectId == to.TradeObjectId 
       || ro.TradeObjectId == myTradeObject.TradeObjectId)) 
       .Select({ 
          var rlt = new RatingListTriangleModel 
           { 
           To1Id = myTradeObject.TradeObjectId, 
           To2Id = to.TradeObjectId, 
           To3Id = ro.TradeObjectId, 
           T1OnT2Rating = 0, 
           T2OnT3Rating = 0, 
           T3OnT1Rating = 0, 
           TotalRating = 0 
          }; 
          this.InsertOrUpdate(rlt); 
          return rlt; 
         }).ToArray(); 
this.Save(); 
+0

找不到在哪里'theseWantMe'集合中查询。谁upvoted这个.. –

+0

我错过了它的第一眼,现予以更正。 – Tilak

+0

'theseWantMe'不是'ro'属性.. –

2

开始通过嵌套循环的骨架转换为LINQ:

var rtls = allCurrentTradeObjects 
    .SelectMany(to => theseWantMe.Select(ro => new {to, ro})); 

这让你对{to, ro}的列表。现在,通过反向continue条件添加过滤:

var rtls = allCurrentTradeObjects 
    .SelectMany(to => theseWantMe.Select(ro => new {to, ro})); 
    .Where(p => p.ro.Type == p.to.Typpe && p.ro.MaxRent >= p.to.Rent && ...) 

最后,添加一个Select叫`新:

var rtls = allCurrentTradeObjects 
    .SelectMany(to => theseWantMe.Select(ro => new {to, ro})); 
    .Where(p => p.ro.Type == p.to.Typpe && p.ro.MaxRent >= p.to.Rent && ...) 
    .Select(p => new RatingListTriangleModel { 
     To1Id = myTradeObject.TradeObjectId, 
     To2Id = p.to.TradeObjectId, 
     To3Id = p.ro.TradeObjectId, 
     ... 
    }); 

随着rtls名单在手,你可以在一个循环中调用InsertOrUpdate

0

为了增加可读性,我将通过重构的复杂状况开始并将其移动到一个整洁的小功能(它也可以是对象的方法)

private bool IsMatchingTradeObject (TradeObject to, SomeOtherObject ro, int TradeObjectId) 
{ 
    return ro.Type == to.Type && 
        ro.MaxRent >= to.Rent && 
        ro.MinRooms <= to.Rooms && 
        ro.MinSquareMeters <= to.SquareMeters && 
        ro.MaxPrice >= to.Price && 
        ro.MinFloors <= to.Floors && 
        ro.TradeObjectId != to.TradeObjectId && 
        ro.TradeObjectId != TradeObjectId; 
} 

其次,我会做与创建相同并初始化RatingListTriangleModel,即将其移动到一个小方法并给它一个有意义的名称。

private RatingListTriangleModel CreateModel(TradeObject to, SomeOtherObject ro, int TradeObjectId) 
{ 
    return new RatingListTriangleModel 
    { 
     To1Id = myTradeObject.TradeObjectId, 
     To2Id = to.TradeObjectId, 
     To3Id = ro.TradeObjectId, 
     T1OnT2Rating = 0, 
     T2OnT3Rating = 0, 
     T3OnT1Rating = 0, 
     TotalRating = 0 
    }; 

剩下的代码更易于阅读

foreach (var to in allCurrentTradeObjects) 
    foreach (var ro in theseWantMe) 
     if (IsMatchingTradeObject(to, ro, myTradeObject.TradeObjectId)) 
     this.InsertOrUpdate(CreateModel(to, ro, myTradeObject.TradeObjectId)); 

this.Save(); 

这个转换为LINQ很简单:

allCurrentTradeObjects.Select (
    to => to.Where ( 
    ro => IsMatchingTradeObject (to, ro, myTradeObject.TradeObjectId) 
    ) 
).Select(
    { 
     this.InsertOrUpdate(CreateModel(to, ro, myTradeObject.TradeObjectId)); 
     return null; 
    } 
); 
this.Save(); 

然而,的foreach循环似乎更容易阅读。

1

有很多答案在这里提倡的SelectMany(或双)。这些是“优化可读性”的答案,因为它们不会改变此操作的N * M嵌套循环性能。

如果这两个集合是大你不应该使用这种方法。相反,您应该利用两个集合之间良好定义的关系,并使用Enumerable.Join中的散列将操作减少到N + M。

var myTradeObject = GetThatOneObject(); 

IEnumerable<RatingListTriangleModel> query = 
    from to in allCurrentTradeObjects 
//pre-emptively filter to the interesting objects in the first collection 
    where to.TradeObjectId == myTradeObject.TradeObjectId 
//take advantage of hashing in Enumerable.Join - theseWantMe is enumerated once 
    join ro in theseWantMe 
    on to.Type equals ro.Type 
//remaining matching criteria 
    where to.Rent <= ro.MaxRent //rent is lower than max 
    && ro.MinRooms <= to.Rooms //rooms are higher than min 
    && ro.MinSquareMeters <= to.SquareMeters //area is higher than min 
    && to.Price <= ro.MaxPrice  //price is lower than max 
    && ro.MinFloors <= to.Floors // floors are higher than min 
    && to.TradeObjectId != ro.TradeObjectId //not same trade object 
    select CreateRatingListTriangleModel(myTradeObject, to, ro); 

foreach(RatingListTriangleModel row in query) 
{ 
    this.InsertOrUpdate(row); 
} 
this.Save(); 
+0

感谢大卫,我尝试过,但我无法弄清楚,为什么我没有收到我的查询任何结果使用这个? –