我如何用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();
答案 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();
答案 1 :(得分: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
。
答案 2 :(得分: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();
答案 3 :(得分: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();
答案 4 :(得分: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循环似乎更容易阅读。