2010-09-19 3 views
7

Ich habe eine Reihe von Modellobjekten mit einer öffentlichen Booleschen Eigenschaft IsVisible. Alles, was ich tun muss, ist herauszufinden, ob mindestens einer der Sätze diesen Wert auf TRUE gesetzt hat. Mit anderen Worten, wenn ich 10.000 Objekte habe, aber das zweite ist true, muss ich nicht durch die anderen 9.998 drehen. Ich habe bereits meine Antwort.Einfache Überprüfung, um festzustellen, ob mindestens ein Objekt in einer Gruppe einen Eigenschaftswert von TRUE hat

Jetzt weiß ich, ich könnte meine eigene Iterationsfunktion schreiben und beim ersten 'True'-Wert ausbrechen, aber ich hoffe, das ist etwas, was LINQ tun kann. Eigentlich muss es nicht einmal LINQ sein. Irgendwelche Vorschläge sind willkommen.

BTW, die Sprache der Wahl ist C#.

Update:

meinen letzten Beitrag hier. Ich habe Testcode und Timings hinzugefügt. Es scheint, dass LINQ im Vergleich zum Test einfach verdammt schlecht ist. Klar, es ist einfacher zu schreiben, aber in missionskritischen Timings bin ich mir nicht mehr sicher.

Was mich überraschte, ist die meiste Zeit habe ich diese, Enumeration gewonnen und durch einen fairen Clip, aber aus irgendeinem Grund, wenn ich den Test in mehreren Durchgängen gewickelt, sieht es aus, um mit einer Indexierung geschaltet haben Cached zählen als am schnellsten.

Ich bemerkte auch, dass, wenn ich nicht alles auf 'falsch' zurücksetze, alle verbleibenden/wiederholten Tests viel schneller scheinen. Irgendwie ändert sich alles, wenn man alles auf FALSE setzt (was absichtlich zu viel ist, um genau das zu testen ...).

Interessant. Ich bin mir nicht sicher, auf welche Art ich jetzt gehen werde. Diese ist nicht ein missionskritisches System, also vielleicht werde ich für Lesbarkeit gehen, aber immer noch. Interessant.

+1

Bei der Optimierung müssen Sie die Ausführungsgeschwindigkeit gegen die Programmierkosten abwägen. Die meisten Entwicklungsmanager würden lieber mehr Server kaufen, als mehr Programmierer bezahlen - und nur ein winziger Bruchteil des Codes läuft auf einem kritischen Pfad. Häufig wird Code, der am schnellsten zu schreiben und zu testen ist, am schnellsten über den Code ausgeführt, wenn alle Kosten (einschließlich Entwicklungskosten) berücksichtigt werden. Nach meiner Erfahrung ist Linq viel schneller zu schreiben, aber langsamer ausgeführt. Es gewinnt immer noch fast die ganze Zeit nach meiner Erfahrung. – Slaggg

+0

Slagg, habe noch nicht genug Punkte, um Kommentare abzugeben, aber weißt du, wenn ich das täte, würdest du dafür einen bekommen. Vielleicht ist es offensichtlich, aber die Prägnanz ist wirklich herausragend (nicht unähnlich dem Punkt, den es auch macht! Klug mein Freund! Sehr schlau!) – MarqueIV

Antwort

16

Die Methode, nach der Sie suchen, ist Enumerable.Any.

bool anyObjectsVisible = myObjects.Any(myObject => myObject.IsVisible); 

Dies ist die genaue Abkürzung Semantik, die Sie suchen; der Beispielcode ähnelt:

static bool AreAnyObjectsVisible(IEnumerable<MyObject> myObjects) 
{ 
    foreach (var myObject in myObjects) 
    { 
     if (myObject.IsVisible) return true; 
    } 

    return false; 
} 
+0

Genau das ist es, wonach ich suche! (Ich bin neu bei LINQ. Kann nicht glauben, dass ich das verpasst habe!) Ich habe versucht, deine Antwort zu akzeptieren, aber es sagt mir, dass ich 12 Minuten warten muss. Ich habe es zumindest gewählt. BTW, guter Gott, das war schnell! War nicht einmal eine Minute her, seit ich es gepostet habe! Du schaukelst! – MarqueIV

+0

@MarqueIV: Prost. Hier ist eine großartige Ressource zu lernen LINQ: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx – Ani

+0

Hey Ari ... nach Ihrem Kommentar, habe ich meine Tests. ABER ... wenn Sie etwas so wortreiches einfügen möchten, aber es ist keine Antwort (d. H. Sie möchten Code-Formatierung, etc.), ist die richtige Etikette, um die ursprüngliche Frage zu bearbeiten? (Ja, Sie haben recht, dass es in diesem Fall eigentlich eine separate Frage sein sollte, aber ich spreche allgemeiner.) – MarqueIV

3

Wenn Sie tatsächlich benötigen ein Objekt zu finden, verwenden Sie einfach die .First oder .FirstOrDefault Methode:

var myObject = myCollection.First(x=>x.IsVisible); 

oder

var myObject = myCollection.FirstOrDefault(x=>x.IsVisible); 

Die einzige Der Unterschied zwischen ihnen besteht darin, dass die Methode .First eine Ausnahme auslöst, wenn kein solches Objekt in der Sammlung vorhanden ist, wenn die zweite Methode den Standardwert zurückgibt (in diesem Beispiel null).

Wenn Sie müssen prüfen nur, ob es ein Objekt mit dieser Eigenschaft ist, verwenden

var thereIsVisibleObject = myCollection.Any(x=>x.IsVisible); 

diese Methoden Alle durch die Sammlung zu stoppen laufe, sobald das entsprechende Objekt gefunden wird.

Oder, sollten Sie überprüfen, ob alle Objekte sind sichtbar/unsichtbar, können Sie dies tun:

var allTheObjectsAreVisible = myCollection.All(x=>x.IsVisible); 
var allTheObjectsAreInvisible = myCollection.All(x=>!x.IsVisible); 

Aber .Alle Methode wird enumerate alle Elemente (die sich aus seinem Namen liegt auf der Hand).

+0

Ich habe dich gewählt, aber Ani hat die "Angenommene Antwort" erhalten, weil sie innerhalb von buchstäblich 60 Sekunden nach der Veröffentlichung geantwortet haben. (Schon bevor ich die Chance hatte, einen Tippfehler zu bearbeiten!) Aber das sind auch viele tolle Infos, also habe ich dich gewählt. Vielen Dank!! – MarqueIV

+0

Ich lese gerade Ihre Kommentare zu 'Alle'. Korrigiere mich, wenn ich falsch liege, aber sie werden NICHT alle Objekte aufzählen, wenn dein Prädikat false zurückgibt, da es sofort false zurückgeben soll, also dein Kommentar, dass sie alles aufzählen werden, wenn ich nicht sicher bin, ob es korrekt ist. Nach dem alle sagen "sind alle sichtbar" sollte Kurzschluss dasselbe wie sagen "sind sie alle nicht sichtbar", wenn sogar eine sichtbar ist, richtig? (Der einzige Unterschied ist, dass der eine wahr, der andere falsch ist.) Natürlich stütze ich das auf Logik und nicht auf Dokumentation, also kann ich nicht sicher sagen. – MarqueIV

+0

Ich bin richtig. .All() durchläuft die Sammlung, die Sie ihm zur Verfügung gestellt haben, und gibt zurück, sobald Ihr Prädikat _false_ ist. –

0

Hier ist ein ".Any()" Umsetzung:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    if (source == null) 
    { 
     throw Error.ArgumentNull("source"); 
    } 
    if (predicate == null) 
    { 
     throw Error.ArgumentNull("predicate"); 
    } 
    foreach (TSource local in source) 
    { 
     if (predicate(local)) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

hier So ist es, nichts "Besonderes" mit .Any(), es ist nur ein Wrapper um "foreach". Nichts Besonderes, um dort zu testen und nichts, was die Mikro-Mikro-Mikro-Optimierung betrifft.

+0

Ihre Optimierungen für Mikro-Mikro-Mikro sind beiseite, es ist immer noch interessant, dass mein Code, der fast identisch mit dem ist, was Sie gepostet haben (ohne Null-Tests), in einigen Fällen bis zu 400% schneller lief als LINQ. Darauf habe ich mich bezogen. – MarqueIV

Verwandte Themen