1

我将如何用 linq 写这个?

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();
4

5 回答 5

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(); 
于 2012-12-29T19:59:02.710 回答
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调用`new:

 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循环调用。

于 2012-12-29T20:03:54.650 回答
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();
于 2012-12-29T20:03:46.257 回答
1

这里有很多提倡 SelectMany (或 double from)的答案。这些是“优化可读性”的答案,因为它们不会更改此操作的 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();
于 2012-12-30T03:36:26.193 回答
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 循环似乎更易于阅读。

于 2012-12-29T20:33:14.723 回答