2016-01-26 19 views
7

Mam tablicę MyClass, które można uprościć następująco:LINQ rozwiązanie dla wielu Rozwiązuje

public class MyClass { 
    public int Id; 
    public string Origin; 
    public int Points; 
    public DateTime RequestTime; 
    public MyClass(int id, string origin, int points, DateTime requestTime) { 
     Id = id; 
     Origin = origin; 
     Points = points; 
     RequestTime = requestTime; 
    } 
} 

Teraz w Array, bez żadnych błędów ze strony użytkownika lub w trakcie procesu wprowadzania, nie może być instancją MyClass z identycznymi Id i Origin.

Jednak, jeśli takie istnieją, powinienem go rozwiązać. A oto zasady rozwiązywania:

  1. po pierwsze Points - czyli podjąć jeden wśród duplikatów, które ma najwyższy Points

  2. Ale jeśli Points są takie same, muszę dalsze rozwiązywanie go za pomocą RequestTime - najnowsze zostaną podjęte.

  3. Jeśli nie ma różnicy w RequestTime, mogę dowolnie pobrać jedno z duplikatów.

Oto przykładowe dane wejściowe mam:

MyClass[] myarr = new MyClass[] { 
    new MyClass(1, "Ware House 1", 5, new DateTime(2016, 1, 26, 14, 0, 0)), //[0] 
    new MyClass(1, "Ware House 1", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[1] //higher points 
    new MyClass(1, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[2] 
    new MyClass(1, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 1, 0)), //[3] //later time 
    new MyClass(1, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[4] 
    new MyClass(2, "Ware House 2", 7, new DateTime(2016, 1, 26, 14, 0, 0)), //[5] //higher points 
    new MyClass(2, "Ware House 2", 5, new DateTime(2016, 1, 26, 14, 1, 0)), //[6] //later time but less points 
    new MyClass(3, "Ware House 1", 6, new DateTime(2016, 1, 26, 14, 0, 0)), //[7] //triplet, pick any 
    new MyClass(3, "Ware House 1", 6, new DateTime(2016, 1, 26, 14, 0, 0)), //[8] //triplet, pick any 
    new MyClass(3, "Ware House 1", 6, new DateTime(2016, 1, 26, 14, 0, 0)) //[9] //triplet, pick any 
}; 

Wynik końcowy powinien być [1], [3], [5], + any of [7]/[8]/[9]

Chcę zaimplementować LINQ rozwiązanie, ale zablokowany. Nie wiem, jak zrobić zapytanie na raz.

Każdy pomysł?

Odpowiedz

8

grupę o {Id, Origin} i ma pierwszy jeden z każdej grupy gdy sortowane według Points i RequestTime:

var query = from x in myarr 
    group x by new {x.Id, x.Origin} 
    into g 
    select (
     from z in g 
     orderby z.Points descending, z.RequestTime descending 
     select z).First(); 

W składni metody, to jest:

var query = 
    myarr.GroupBy(x => new {x.Id, x.Origin}) 
     .Select(g => g.OrderByDescending(z => z.Points) 
         .ThenByDescending(z => z.RequestTime) 
         .First()); 
+0

To działa! Dzięki! : D Przyjmę to tak szybko, jak tylko będę mógł ... – Ian

+0

ah, widzę, że trik polega na "grupowaniu" zarówno Id, jak i Origin, zanim kolejność porządkowa się dwa razy. Nie wiedziałem wcześniej, że możemy pogrupować według dwóch pozycji. Myślałem o zrobieniu podwójnego "GroupBy", które nie wydawało się dobrym pomysłem ze względu na naturę "klucza złożonego". Wielkie dzięki! :) – Ian

+1

@Ian Yep, anonimowe typy są twoim przyjacielem w grupowaniu i dołączaniu. –

0

Spróbuj następujące:

myarr.OrderBy(m=> m.Points).ToList(); 

lub

myarr.OrderBy(m=> m.Points).Orderby(m=> m.RequestTime); 
+0

Dzięki za szybką odpowiedź ... Aby zamówić sam nie jest trudne, ale gdzie utknąłem kiedy próbowałem usunąć duplikaty oparte na zasadach rozwiązywania. Dowolny pomysł? – Ian

+0

dit widać następujący post: http://stackoverflow.com/questions/1606679/remove-duplicates-in-the-list-using-linq –