2016-02-03 23 views
5

Mam podchwytliwe pytanie. Szukam najbardziej zwięzły, hackiest drodze osiągnięcia następujących:Grupa alfabetyczna w Linq z niespodzianką

query = (from book in library.books.OrderBy(x=>x.title) 
     group book by 
     new { title = book.title[0].ToString(), yadiyada="" }); 

wyniku której to wszystkie książki w bibliotece pogrupowane według pierwszej litery. Yadiyada jest, ponieważ mój obiekt grupy nie jest prosty ciąg, ale obiekt.

Zastanawiam się, czy istnieje czysty sposób LINQ tak, aby grupa była "A", "B", "C", ... "Z", ale wszystkie inne należą do jednego grupowanie o nazwie "123! @ #".

Innymi słowy, chcę tylko jedno zgrupowanie dla wszystkich znaków innych niż alfa (A-> Z + Rest).

Mogę to zrobić na wiele sposobów, jeśli otrzymam pełną informację (obecnie po prostu dokonuję połączenia dwóch zdań Linq), ale nie jest to celem tego pytania. Zastanawiam się, czy ktoś może wymyślić naprawdę fajny sposób robienia tego ...

Odpowiedz

8

To zależy od tego, co znaczy czysty sposób LINQ. Jeśli chcesz pogrupować go za pomocą pojedynczego zapytania, możesz spróbować czegoś takiego:

query = (from book in library.books.OrderBy(x=>x.title) 
     let c = book.title[0] 
     group book by 
     new { title = char.IsLetter(c) ? c.ToString() : "[email protected]#", yadiyada="" }); 
+0

Niesamowite. Właśnie tego rodzaju konstrukcji szukałem, ale nie mogłem myśleć. Dzięki! –

+2

'char.IsLetter' nie jest obsługiwane przez linq do encji. – dotctor

+1

Zwróć uwagę, że 'char.IsLetter' zwraca wartość true dla ponad 47000 znaków, w przeciwieństwie do mojego' HashSet', poniżej którego akceptuje tylko a-z/A-Z. To może być pożądane lub nie. –

0

Myślę, że chcesz jakiegoś warunkowego grupowania. Możesz użyć znaku pustego jako symbolu zastępczego dla wszystkich znaków innych niż alfa:

HashSet<char> alpha = new HashSet<char>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvqxyz"); 

var query = books 
    .OrderBy(b => b.title) 
    .Select(b => new{ Book = b, IsAlpha = alpha.Contains(b.title[0]), Char = b.title[0]}) 
    .Select(x => new{ x.IsAlpha, x.Book, Char = x.IsAlpha ? x.Char : '\0' }) 
    .GroupBy(x => x.Char); 
+1

To jest bliższe temu, co robiłem (używając zakresu zamiast jawnie). Ale odpowiedź Eldara Dordżewa jest znacznie bardziej elegancka. –

+0

czy to rozwiązanie nie jest drogie od zaakceptowanego? –

+0

@ EhsanSajjad: dlaczego myślisz, że to jest drogie? Musi utworzyć instancje anonimowych obiektów. Ale imo jest mikro-optinmizing, jeśli starasz się go uniknąć bez powodu. –