2013-03-11 4 views
7

Kiedy chcę pobrać obiekt o najwyższej wartości nieruchomości DateTime z IEnumerable, mogę wykonać następujące czynności:Pierwsze obiekt o max aktualna wartość czasu w jednym z nim jest właściwości

var maxDate = myEnumerable.Max(x => x.TheDateTimeProperty); 
var wantedObject = myEnumerable.FirstOrDefault(x => x.TheDateTimeProperty == maxDate); 

Czy to możliwe bez wcześniejszego uzyskania maxDate? Na przykład takich jak to:

var wantedObject = myEnumerable.GetByMaxDate(x => x.TheDateTimeProperty); 

wiem, że mógłbym napisać metodę rozszerzenia GetByMaxDate, ale chcę wiedzieć, czy istnieje już sposób dostarczone przez LINQ.

Aby wyjaśnić: Nie szukam innych możliwości napisania tego. Byłem tylko zainteresowany, czy istnieje metoda, która to robi. (Mniej kodu, możliwe najlepszą wydajność udało metodą)

+2

Możesz użyć [morelinq] (https://code.google.com/p/morelinq /) autorstwa Jona Skeeta i jego metody [MaxBy] (https://code.google.com/p/morelinq/source/browse/MoreLinq/MaxBy.cs?r=2da75c30d5bda7959e5113b702b4bb204a0e4a2c) – Habib

+0

Po drugie, pojęcie że powinieneś użyć metody MaxBy z morelinq. Powinien być w każdym przyborniku programisty C#! –

+0

Więc nie ma metody wbudowanej przez linq, dziękuję za informację o tym! –

Odpowiedz

0

Ponieważ nie idą żadne inne odpowiedzi i tam nie istnieć wbudowany metody w LINQ, będę spisać to, co chciałbym użyć.

Dla LINQ do obiektów:

Sposób MaxBy z morelinq jak wspomniano przez Habib w komentarzu.

Dla LINQ do SQL:

chciałbym napisać metodę rozszerzenia. Próbowałem tego, ale poniższy kod nie działa jeszcze. Jeśli ktoś wie, co jest nie tak, edytuj odpowiedź. Spróbuję to rozgryźć, kiedy mam trochę czasu.

public static TSource SqlMaxBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector) 
{ 
    var maxValue = source.Max(selector); 
    return source.FirstOrDefault(selector == maxValue); 
} 
10

Pro: powinien pracować z "każdym" dostawcy linq (obiekty, podmioty, SQL)

myEnumerable.OrderByDescending(x => x.TheDateTimeProperty).First(); 

Con: jak wskazał Matthew Watson w komentarzach , nie będzie działać na (bardzo) dużych listach.

+0

Ma to tę główną wadę, że tworzy kopię całej sekwencji, a następnie sortuje ją tylko po to, aby uzyskać maksymalną wartość. Dobra dla małych list ... bardzo źle dla długich list. –

+0

@MatthewWatson absolutnie. Po prostu pytanie (jeśli masz odpowiedź), czy MaxBy działa na wszystkich dostawcach linq, takich jak linq do podmiotów? Z podanym kodem źródłowym wygląda tak, jak wylicza, co jest ... nie świetne dla IQueryable. –

+0

Nie dokładnie to, czego szukałem, to da mi wynik, ale byłem zainteresowany, czy istnieje metoda, którą mogę użyć, która to robi (z dobrą wydajnością) –

2

Preferuję uzyskać maxDate pierwszy, jak pierwotnie stwierdzono. Nie widzę problemu przy użyciu składni, która już była używana.

Jednak jeśli chcesz, możesz skrótowym kod tak:

var wantedObject = myEnumerable.FirstOrDefault(x => x.TheDateTimeProperty == myEnumerable.Max(x => x.TheDateTimeProperty)); 

(Ten kod nie jest testowana, może potrzebny jakiś rodzaj odlewu)

Albo można napisać procedurę przechowywaną i podejmują dane z tego.

Jednak nie wolę już OrderByDescending.First. Jest to w porządku, jeśli fizycznie dane w tabeli są posortowane rosnąco według określonej właściwości. Ale jeśli nie, to twoja tabela sql będzie musiała zrobić sortowanie malejąco i prawdopodobnie uzyskać wysokie obciążenie z niego. Zwłaszcza, gdy tabela ma ponad 1m rekordu, a Data jest przechowywana w kolejności fizycznej.

Użyj maksimum może wynik lepszy (szybciej/lżejszy) niż wynik.

+0

Nie chciałem zapytać, czy istnieje inny sposób bez zapisania maxDate w zmiennej najpierw . Zmienię moje pytanie, aby to wyjaśnić. –

+0

Tak, wiem, pokazując skrót jako dodatkowy. Jak na moje zrozumienie, to co osiągnąłeś już wystarczająco dobry i wystarczająco lekki. Być może możesz uzyskać lepszą odpowiedź, jeśli opisałeś swój problem ze składnią. Jeśli jednak chcesz osiągnąć lepsze wyniki, zastanów się nad użyciem procedury przechowywanej, w której możesz dostroić zapytanie lub poprawić za pomocą indeksów. – Fendy

+0

Moje pytanie nie dotyczy konkretnie linq-sql, ale jeśli ktoś chce to w tym kontekście, to jest dobry punkt! –

Powiązane problemy