2010-02-17 15 views
7

Ich habe mich LINQ vor kurzem gelehrt und es auf verschiedene kleine Rätsel angewendet. Eines der Probleme, auf die ich gestoßen bin, ist jedoch, dass LINQ-to-objects nur in generischen Sammlungen funktioniert. Gibt es einen geheimen Trick/Best Practice zum Konvertieren einer nicht generischen Sammlung in eine generische Sammlung?Wie konvertiert man eine nicht generische Sammlung am besten in eine generische Sammlung?

Meine aktuelle Implementierung kopiert die nicht-generische Sammlung in ein Array und arbeitet dann daran, aber ich fragte mich, ob es einen besseren Weg gab?

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

Antwort

10

Der einfachste Weg ist in der Regel die Cast Erweiterungsmethode:

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

Beachten Sie, dass diese aufgeschoben und Bäche seine Daten, so dass Sie nicht eine vollständige „Sammlung“ als solche - Aber es ist eine vollkommen gute Datenquelle für LINQ-Abfragen.

So konvertieren Sie Ihre Abfrage komplett:

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

oder

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

In der Tat

Cast automatisch, wenn Sie einen Typ für die Bereichsvariable in einem Abfrageausdruck angeben genannt , müssen Sie nicht OrderByDescending anrufen und dann First hier - Sie wollen nur den maximalen Wert, der die Max Methode bekommt Sie. Noch besser ist, können Sie damit einen Vorsprung von einem Quellelementtyp angeben, um den Wert, den Sie zu finden sind versuchen, so dass Sie ohne die Select auch tun:

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

Wenn Sie eine Sammlung, die einige hat Elemente des richtigen Typs, aber einige, die nicht sein können, können Sie stattdessen OfType verwenden. Cast löst eine Ausnahme aus, wenn ein Element vom Typ "falsch" gefunden wird. OfType überspringt es einfach.

+0

Vielen Dank! Ich bin mir nicht sicher, wie ich diese Methode in der Dokumentation vermisst habe, aber genau das habe ich gesucht! Danke auch für den Tipp auf Max() – guhou

0
matches.Cast<Match>(); 
1

Sie können Cast oder OfType auf eine IEnumerable konvertieren. Cast wird den illegalen Cast auslösen, wenn das Element nicht in den angegebenen Typ umgewandelt werden kann, während OfType Elemente überspringt, die nicht konvertiert werden können.

Verwandte Themen