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 の呼び出しに a を追加します。

 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 ネストされたループのパフォーマンスを変更しないという点で、「読みやすくするために最適化する」回答です。

両方のコレクションが大きい場合は、このアプローチを使用しないでください。代わりに、2 つのコレクション間の明確に定義された関係と、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 に答える