我在流畅的LINQ中遇到了一个问题,即选择一个父项和一个孩子为Ienumerable < anonymous type>
。
为简单起见:
有一个commanders
的列表(每个地区的指挥官)。
每个指挥官都有自己的 List of Soldiers
。 (并且每个Soldier
都有一个bool属性IsCanWinWar
和一个Tool
,用于与之斗争)
我想列出 每个 指挥官(谁拥有一个或多个 solider 谁可以获胜战争)和该士兵使用的一个tool
名称。
我不在乎指挥官是否有超过一名可以赢得战争的士兵。
所有指挥官需要的是其中一名士兵(可以赢得战争)的tool
(从不介意哪种工具)。
输出为Ienumerable < anonymous type>
,其中匿名类型如下:
{
theCommander = [commanderObject] ,
theToolName = [the tool name ]
}
我用selectMany
做了一些事,但它很长很难看。
是否有任何简短的查询(流畅的查询)可以更短的方式产生相同的结果?
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= ?
}
答案 0 :(得分:2)
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);
如果没有可以赢得战争的士兵,那么工具将为空。只需在选择后过滤掉那些指挥官。
BTW我认为Soldiers
是一个更好的属性名称,然后lstSoldiers
(它没有前缀,它是PascalCase)。
答案 1 :(得分:1)
第一种方法(稍后修订):
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 };