LINQ Tek bir satır seçmek için Max () kullanma


98

NHibernate'den dönen bir IQueryable üzerinde LINQ kullanıyorum ve birkaç alandaki maksimum değer (ler) i içeren satırı seçmem gerekiyor.

Yapıştırdığım kısmı basitleştirdim. Tablomdan bir alandaki maksimum değeri olan bir satırı seçmem gerekiyor.

var table = new Table { new Row(id: 1, status: 10), new Row(id: 2, status: 20) }

from u in table
group u by 1 into g
where u.Status == g.Max(u => u.Status)
select u

Bu yanlış ama doğru formu bulamıyorum.

BTW, aslında başarmaya çalıştığım şey yaklaşık olarak şudur:

var clientAddress = this.repository.GetAll()
    .GroupBy(a => a)
    .SelectMany(
            g =>
            g.Where(
                a =>
                a.Reference == clientReference && 
                a.Status == ClientStatus.Live && 
                a.AddressReference == g.Max(x => x.AddressReference) && 
                a.StartDate == g.Max(x => x.StartDate)))
    .SingleOrDefault();

Yukarıdaki lambda ile başladım ama Max () 'i seçmek için sözdizimini denemek ve çalışmak için LINQPad kullanıyorum.

GÜNCELLEME

GroupBy'yi kaldırmak anahtardı.

var all = this.repository.GetAll();

var address = all
            .Where(
                a =>
                a.Reference == clientReference && 
                a.Status == ClientStatus.Live && 
                a.StartDate == all.Max(x => x.StartDate) &&
                a.AddressReference == all.Max(x => x.AddressReference))
            .SingleOrDefault();


@ M.Babcock bu soruya epeyce iyi bir cevap vardı: stackoverflow.com/a/6330485/444244
Boggin

Bundan daha iyileri var ...
M.Babcock

Bir göz atın cevap .
Sergey Brunov

@Serge Morelinq'in en iyisi olduğuna katılıyorum ama korkarım bu proje yeni kütüphaneler eklemeye engel teşkil ediyor.
Boggin

Yanıtlar:


235

Neden burada gruplaştığını anlamıyorum.

Bunu dene:

var maxValue = table.Max(x => x.Status)
var result = table.First(x => x.Status == maxValue);

tableYalnızca bir kez yinelenen alternatif bir yaklaşım şudur :

var result = table.OrderByDescending(x => x.Status).First();

Bu, bellekte mevcut olmayan veya anında hesaplanan tablebir IEnumerable<T>şeyse yararlıdır .


1
Gruplamayı çıkardım ve çalıştırabileceğimi fark ettim: from u in User_Accounts where u.Status == User_Accounts.Max(y => y.Status) select u
Boggin

1
Ayrıca lambda sözdizimini iç içe yerleştirebilirsiniz: table.First(x => x.Status == table.Max(x => x.Status))
Landon Poch

15
@LandonPoch: Bu iyi bir fikir değil, çünkü bu, N'nin içindeki öğe sayısı olduğu maksimum N sayısını hesaplayacaktır table.
Daniel Hilgarth

2
@Daniel Hilgarth: İyi yakaladın! Bu aslında tablodaki her satır için maksimum değeri hesaplar. Benim hatam.
Landon Poch

18

Ayrıca şunları da yapabilirsiniz:

(from u in table
orderby u.Status descending
select u).Take(1);

13

Duruma göre gruplayabilir ve en büyük gruptan bir satır seçebilirsiniz:

table.GroupBy(r => r.Status).OrderByDescending(g => g.Key).First().First();

İlki ilk First()grubu alır (en büyük duruma sahip satırlar kümesi); ikincisi First()bu gruptaki ilk satırı alır.
Durum her zaman değişmiyorsa, ikinciyi First()ile değiştirebilirsiniz Single().


7

İlk soruyu ele alırsak, belirli kriterlere göre gruplandırılmış birkaç satır ve maksimum değeri olan diğer sütunu almanız gerekiyorsa, aşağıdaki gibi bir şey yapabilirsiniz:

var query =
    from u1 in table
    join u2 in (
        from u in table
        group u by u.GroupId into g
        select new { GroupId = g.Key, MaxStatus = g.Max(x => x.Status) }
    ) on new { u1.GroupId, u1.Status } equals new { u2.GroupId, Status = u2.MaxStatus}
    select u1;

0

Daha fazla örnek:

Takip et:

 qryAux = (from q in qryAux where
            q.OrdSeq == (from pp in Sessao.Query<NameTable>() where pp.FieldPk
            == q.FieldPk select pp.OrdSeq).Max() select q);

Eşittir:

 select t.*   from nametable t  where t.OrdSeq =
        (select max(t2.OrdSeq) from nametable t2 where t2.FieldPk= t.FieldPk)

-1

Basitçe tek satırda:

var result = table.First(x => x.Status == table.Max(y => y.Status));

İki eylem olduğuna dikkat edin. iç eylem maksimum değeri bulmak içindir, dış eylem ise istenen nesneyi elde etmek içindir.


Bu yöntem, kötü bir fikir olduğuna işaret edildiği kabul edilen cevaba yapılan yorumlarda tartışıldı.
Boggin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.