एक पंक्ति का चयन करने के लिए अधिकतम () का उपयोग कर LINQ


95

मैं NHibernate से लौटे एक IQueryable पर LINQ का उपयोग कर रहा हूं और मुझे कुछ क्षेत्रों में अधिकतम मूल्य (s) के साथ पंक्ति का चयन करने की आवश्यकता है।

मैंने थोड़ा सा सरलीकृत किया है जिस पर मैं चिपका हूं। मुझे अपनी तालिका में से एक पंक्ति का चयन एक क्षेत्र में अधिकतम मान के साथ करने की आवश्यकता है।

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

यह गलत है लेकिन मैं सही फॉर्म नहीं दे सकता।

BTW, जो मैं वास्तव में प्राप्त करने की कोशिश कर रहा हूं वह लगभग यही है:

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();

मैंने उपरोक्त लैम्बडा के साथ शुरुआत की है लेकिन मैं अधिकतम () का चयन करने के लिए वाक्यविन्यास को आजमाने और काम करने के लिए LINQPad का उपयोग कर रहा हूं।

अपडेट करें

GroupBy निकालना महत्वपूर्ण था।

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();

संभव डुप्लिकेट: stackoverflow.com/questions/1101841/…
M.Babcock

@ M.Babcock उस सवाल में काफी दूर एक अच्छा जवाब था: stackoverflow.com/a/6330485/444244
15

इससे बहुत बेहतर हैं ...
15


@ मैं सहमत हूं कि मोरेलिनैक सबसे अच्छा होगा लेकिन मुझे डर है कि इस परियोजना में नए पुस्तकालयों को जोड़ने के लिए बाधाएं हैं।
बोगिन

जवाबों:


230

मैं नहीं देखता कि आप यहां समूह क्यों बना रहे हैं।

इसे इस्तेमाल करे:

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

एक वैकल्पिक दृष्टिकोण जो tableकेवल एक बार पुनरावृति करेगा वह यह होगा:

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

यह मददगार है अगर tableऐसा है जो IEnumerable<T>स्मृति में मौजूद नहीं है या जिसकी गणना मक्खी पर की जाती है।


1
मैंने समूह बना लिया और पाया कि मैं यह काम कर सकता हूँ: from u in User_Accounts where u.Status == User_Accounts.Max(y => y.Status) select u
बोगिन

1
आप लैम्ब्डा सिंटैक्स को भी घोंसला बना सकते हैं: table.First(x => x.Status == table.Max(x => x.Status))
लैंडन पोच

13
@LandonPoch: यह एक अच्छा विचार नहीं है, क्योंकि यह अधिकतम N बार N की गणना करेगा जिसमें आइटमों की संख्या होगी table
डैनियल हिल्गर्थ

2
@ डैनियल हिलगार्थ: अच्छा कैच! यह वास्तव में तालिका में प्रत्येक पंक्ति की अधिकतम गणना करेगा। मेरी गलती।
लन्दन पोच


13

आप स्थिति से समूह बना सकते हैं और सबसे बड़े समूह में से एक पंक्ति का चयन कर सकते हैं:

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

पहले First()को पहला समूह मिलता है (सबसे बड़ी स्थिति के साथ पंक्तियों का सेट); दूसरे First()को उस समूह में पहली पंक्ति मिलती है।
स्थिति है हमेशा unqiue, आप दूसरी जगह ले सकता है First()के साथ Single()


7

पहले प्रश्न को संबोधित करते हुए, यदि आपको अधिकतम मान के साथ दूसरे स्तंभ के साथ कुछ मानदंडों द्वारा समूहीकृत कई पंक्तियों को लेने की आवश्यकता है, तो आप कुछ ऐसा कर सकते हैं:

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

एक और उदाहरण:

का पालन करें:

 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);

बराबर है:

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

-1

बस एक लाइन में:

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

ध्यान दें कि दो कार्रवाई हैं। आंतरिक कार्रवाई अधिकतम मूल्य खोजने के लिए है, बाहरी कार्रवाई वांछित वस्तु प्राप्त करने के लिए है।


इस पद्धति पर टिप्पणियों में स्वीकार किए गए उत्तर पर चर्चा की गई थी जहां बताया गया था कि यह एक बुरा विचार था।
बोगिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.