LINQ C#获取列表中的最后一个元素(基于名称)

时间:2012-01-13 01:44:14

标签: c# linq anonymous-types

我有这个清单:

安妮 - P
五月 - “” 安妮 - P
五月 - P

我想根据名字得到最后一个元素:

安妮 - P
五月 - P

我有这个代码,但它要么抛出一个错误:The type arguments for method 'System.Linq.Enumerable.SelectMany<TSource,TResult>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,System.Collections.Generic.IEnumerable<TResult>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.,要么我只得到列表中的最后一个元素(May-P)。

class Passenger
{
    public string Name { get; set; }
    public int PassengerID { get; set; }
    public List<TravelDoc> TravelDocs { get; set; }
}

class TravelDoc
{
    public string DocType { get; set; }
    public int? DocNumber { get; set; }
}

List<Passenger> modList = new List<Passenger>()
    {

        new Passenger() { Name = "Annie", PassengerID = 0, 
                          TravelDocs = new List<TravelDoc>()
                          {
                            new TravelDoc() { DocNumber = 100, DocType = "P" }
                          }
                        },
        new Passenger() { Name = "May", PassengerID = 1, 
                          TravelDocs = new List<TravelDoc>()
                          {
                            new TravelDoc() { DocNumber = null, DocType = "" }
                          }
                        },      
        new Passenger() { Name = "Annie", PassengerID = 0, 
                          TravelDocs = new List<TravelDoc>()
                          {
                            new TravelDoc() { DocNumber = 100, DocType = "P" }
                          }
                        },
        new Passenger() { Name = "May", PassengerID = 1, 
                          TravelDocs = new List<TravelDoc>()
                          {
                            new TravelDoc() { DocNumber = 200, DocType = "P" }
                          }
                        }
    };      

代码(引发错误)

var passengersMod = modList.SelectMany(pax => pax.TravelDocs         
                    .Select(doc => new { Passenger = pax, TravelDoc = doc })
                    .Last())
                    .Dump();

代码(错误的结果)

var passengersMod = modList.SelectMany(pax => pax.TravelDocs         
                    .Select(doc => new { Passenger = pax, TravelDoc = doc })
                    ).Last()
                    .Dump();

注意: Dump()是LINQPad扩展。 :d

如何使用LINQ获得我想要的结果?

提前致谢。

修改

好吧,似乎大多数人都对“基于姓名”的情况感到困惑。对此感到抱歉,但遗憾的是我无法想出任何更好的词语来描述标准(抱歉)。但Jon Hanna得到了我的意思,谢谢!我也按照建议从标题中删除了“匿名类型”。再次感谢! :d

另一个编辑:

我有另一种与此类似的情况,略有不同。是的,列表是根据某些标准(在此示例中按名称)分组,但不是需要每个分组中的最后一项,我需要的是每个分组中的第n项。

我能够从每个分组中获得第n个:

modList.GroupBy(p => p.Name).Select(g => g.ToList()[index])

在我问这个问题多年后,Jon的回答仍然帮助了我。我多么希望能两次回答他的答案!我希望这可能对其他人有所帮助。 :d

3 个答案:

答案 0 :(得分:4)

为什么不忽略匿名类型和SelectMany而只是这样做:

modList.GroupBy(p => p.Name).Select(g => g.Last())

根据你的标题,它与匿名类型无关,但它确实会导致你在问题开头提到的那种结果。

答案 1 :(得分:1)

首先,SelectMany用于将多个集合聚合为一个集合。考虑转换IEnumerable&lt; IEnumerable&lt; int&gt;&gt;成一个IEnumerable&lt; int&gt;。因此无法推断使用,因为Last方法将返回不表示IEnumerable对象的单个元素。现在我不太明白你所说的“基于名字的最后元素”是什么意思,但如果你想获得你馆藏中的最后N个元素,你可以做类似的事情:

// This will return the last 2 elements in your collection.
modList.Skip(modList.Count() - 2);

答案 2 :(得分:1)

我不确定我是否理解您如何订购这些物品,但我认为您要做的是:

var passengersMod = modList.SelectMany(
    d => d.TravelDocs, (p, d) => new { Passenger = p, TravelDoc = d })
   .Last()
   .Dump();