2010-02-17 9 views
7

Uczę się ostatnio LINQ i stosuję go do różnych małych zagadek. Jednak jednym z problemów, które napotkam, jest to, że LINQ-to-Object działa tylko na kolekcjach ogólnych. Czy istnieje tajna sztuczka/najlepsza praktyka przekształcania nietypowej kolekcji w kolekcję ogólną?Jaki jest najlepszy sposób na konwersję kolekcji nietypowej na kolekcję ogólną?

Moja obecna implementacja kopiuje kolekcję nietypową do tablicy, po czym działa na tym, ale zastanawiałem się, czy istnieje lepszy sposób?

public static int maxSequence(string str) 
{ 
    MatchCollection matches = Regex.Matches(str, "H+|T+"); 
    Match[] matchArr = new Match[matches.Count]; 
    matches.CopyTo(matchArr, 0); 
    return matchArr 
     .Select(match => match.Value.Length) 
     .OrderByDescending(len => len) 
     .First(); 
} 

Odpowiedz

10

Najprostszym sposobem jest zazwyczaj metoda Cast rozszerzenie:

IEnumerable<Match> strongMatches = matches.Cast<Match>(); 

pamiętać, że jest odraczane i strumieni swoje dane, więc nie ma pełnego „zbieranie” jako takiego - ale jest to doskonałe źródło danych dla zapytań LINQ.

Cast jest wywoływana automatycznie, jeśli określić typ dla zmiennej zakres w wyrażeniu kwerendy:

Więc przekonwertować zapytanie całkowicie:

public static int MaxSequence(string str) 
{  
    return (from Match match in Regex.Matches(str, "H+|T+") 
      select match.Value.Length into matchLength 
      orderby matchLength descending 
      select matchLength).First(); 
} 

lub

public static int MaxSequence(string str) 
{  
    MatchCollection matches = Regex.Matches(str, "H+|T+"); 
    return matches.Cast<Match>() 
        .Select(match => match.Value.Length) 
        .OrderByDescending(len => len) 
        .First(); 
} 

W rzeczywistości , nie musisz zadzwonić pod numer OrderByDescending, a następnie First tutaj - chcesz tylko maksymalną wartość, która Max metoda dostaje ciebie. Jeszcze lepiej, to pozwala określić projekcję od typu elementu źródłowego do wartości starasz się znaleźć, więc można zrobić bez Select też:

public static int MaxSequence(string str) 
{  
    MatchCollection matches = Regex.Matches(str, "H+|T+"); 
    return matches.Cast<Match>() 
        .Max(match => match.Value.Length); 
} 

Jeśli masz kolekcję, która ma trochę elementy odpowiedniego typu, ale niektóre, które mogą nie być, można zamiast tego użyć OfType. Cast zgłasza wyjątek, gdy napotka element "niewłaściwego" typu; OfType po prostu przeskakuje nad nim.

+0

Dziękuję bardzo! Nie jestem pewien, jak ominąłem tę metodę w dokumentacji, ale tego właśnie szukałem! Również dziękuję za poradę dotyczącą używania Max() – guhou

0
matches.Cast<Match>(); 
1

Możesz użyć Cast lub OfType na IEnumerable do konwersji. Cast rzuca nielegalny rzut, jeśli element nie może być rzutowany na określony typ, natomiast OfType pominie wszelkie elementy, których nie można przekonwertować.

Powiązane problemy