C#中的父子流利Linq查询
本文关键字:Linq 查询 父子 | 更新日期: 2023-09-27 18:02:36
我在fluent LINQ中遇到了一个问题,用于将父级和子级选择到一个Ienumerable < anonymous type>
中
为了简单起见:
-
有一个
commanders
(每个地区的指挥官(的列表。 -
每个指挥官都有自己的
List of Soldiers
。(每个Soldier
都有一个布尔属性IsCanWinWar
和一个他用来对抗的Tool
(
我想列出每个指挥官(有一个或多个能赢得战争的士兵(和该士兵使用的一个tool
名称。
我不在乎一个指挥官是否有不止一个能赢得战争的士兵。
指挥官所需要的只是一名士兵(能够赢得战争(的tool
(别管是哪种工具(。
输出为Ienumerable < anonymous type>
,其中匿名类型类似于:
{
theCommander = [commanderObject] ,
theToolName = [the tool name ]
}
我用selectMany
做了一些事情,但它又长又丑
是否有任何短查询(fluent query(可以以更短的方式产生相同的结果?
public class Commander
{
public List<Soldier> lstSoldiers =new List<Soldier>(); //from db actually.
}
public class Soldier
{
public bool IsCanWinWar { get; set; }
public string Tool { get; set; }
}
void Main()
{
List<Commander> lstCommanders = new List<Commander>(); //data source is actually from db.
var MyIernumerableOfAnonymouseTypes= ?
}
var MyIernumerableOfAnonymouseTypes =
lstCommanders.Select(c => new {
theCommander = c,
theToolName = c.lstSoldiers.Where(s => s.IsCanWinWar)
.Select(s => s.Tool)
.FirstOrDefault() })
.Where(x => x.theToolName != null);
若并没有一个士兵能够赢得战争,那个么这个工具将是无效的。只要筛选出那些指挥官。
顺便说一句,我认为Soldiers
是一个更好的属性名称,而不是lstSoldiers
(它没有前缀,是PascalCase(。
第一种方法(稍后修订(:
from commander in lstCommanders
where commander.lstSoldiers.Any(soldier => soldier.IsCanWinWar) // Consider only commanders who have at least one soldier who can win the war
select new
{
Commander = commander,
Tool = (from soldier in commander.lstSoldiers
where soldier.IsCanWinWar // Consider tool originating from soldiers who can win the war
select soldier.Tool).FirstOrDefault()
};
第二个更简洁、更快:
from commander in lstCommanders
where commander.lstSoldiers.Any(soldier => soldier.IsCanWinWar)
select new { Commander = commander, Tool = commander.lstSoldiers.First(soldier => soldier.IsCanWinWar).Tool };
以流畅的方式:
lstCommanders.Where(commander => commander.lstSoldiers.Any(soldier => soldier.IsCanWinWar))
.Select( commander => new
{
Commander = commander,
Tool = commander.lstSoldiers.First(soldier => soldier.IsCanWinWar).Tool
});
一次迭代的第三个选项:
from commander in lstCommanders
let winner = commander.lstSoldiers.FirstOrDefault(soldier => soldier.IsCanWinWar)
where null != winner // Consider only commanders who have at least one soldier who can win the war
select new { Commander = commander, Tool = winner.Tool };