父母和孩子在C#中流利的Linq查询?

时间:2013-03-06 11:02:18

标签: c# .net linq

我在流畅的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= ?
}

2 个答案:

答案 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 };