Leiv Halvor Lauvsnes
Leiv Halvor Lauvsnes

Reputation: 146

Linq Lambda get two properties as string from aggretation

Inside a linq query to an anonymous select I want to concatenate strings from two properties.

For instance to find the full name of the oldest person in some grouping of persons.

var personsAndOldest = db.Persons.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson).Select(a => new
            {
                FirstName = a.FirstOrDefault().FirstName,
                LastName = a.FirstOrDefault().LastName,
                BirthDate = a.FirstOrDefault().BirthDate,
                FullnameOfOldes = a.Aggregate((pers1, pers2) => pers1.BirthDate > pers2.BirthDate ? pers1 : pers2).FirstName + " " //How do I get LastName of the old one (without using the full aggregate again)
            });

Do I have to write the full aggregation again to get the LastName after the firstname and whitespace?

Upvotes: 5

Views: 879

Answers (3)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236248

  • You can use let to introduce new range variables.
  • You don't need to specify property name for anonymous type if it equals name of assigned property
  • I think OrderBy will find oldest person (but you can use aggregate and compare performance)
  • I believe that oldest person is one with minimal birth date, so you need to change aggregation to pers1.BirthDate < pers2.BirthDate ? pers1 : pers2

So

var personsAndOldest = from p in db.Persons
                       group p by p.SomeThingThatCanBeGroupedForPerson into g
                       let first = g.FirtOrDefault()
                       let oldest = g.OrderBy(x => x.BirthDate).FirstOrefault()
                       select
                       {
                           first.FirstName,
                           first.LastName,
                           first.BirthDate,
                           FullnameOfOldes = oldest.FirstName + " " + oldest.LastName
                       };

Upvotes: 0

Rawling
Rawling

Reputation: 50114

You can do this as

var personsAndOldest = db.Persons
    .GroupBy(person => person.SomeThingThatCanBeGroupedForPerson)
    .Select(g => new 
        {
            a = g.First(),
            o = g.Aggregate((pers1, pers2) =>
                pers1.BirthDate > pers2.BirthDate ? pers1 : pers2)
        })
    .Select(pair => new
        {
            FirstName = pair.a.FirstName,
            LastName = pair.a.LastName,
            BirthDate = pair.a.BirthDate,
            FullnameOfOldes = pair.o.FirstName + " " + pair.o.LastName
        });

Upvotes: 1

Eren Ers&#246;nmez
Eren Ers&#246;nmez

Reputation: 39085

You could use a lambda statement in the Select:

var personsAndOldest = db.Persons.GroupBy(person => person.SomeThingThatCanBeGroupedForPerson).Select(a => 
    {
        var first = a.First();
        var oldest = a.Aggregate((pers1, pers2) => pers1.BirthDate > pers2.BirthDate ? pers1 : pers2);
        return new
        {
            FirstName = first.FirstName,
            LastName = first.LastName,
            BirthDate = first.BirthDate,
            FullnameOfOldes = oldest.FirstName + " " + oldest.LastName)
        };
    });

Upvotes: 1

Related Questions