Zählen der Anzahl der Punkte, die sowohl einen größeren Theta-Wert als auch einen größeren Radius haben als ein bestimmter Punkt

1277
mjcopple

Die Tatsache, dass ich alle Punkte auswähle, gefällt mir nicht, auch wenn mir nur die Anzahl der Punkte wichtig ist.

Welcher der fromTeile sollte zuerst erscheinen, wenn es überhaupt eine Rolle spielt?

var count = (from type in ValidTypes()
    from point in GetData(type)
    where point.Radius > referencePoint.Radius
        && point.Theta > referencePoint.Theta
    select point).Count()

ValidTypes() gibt einige Typen zurück, ungefähr 5.

GetData(type) kann viele Punkte zurückgeben, möglicherweise 100.000.

Diese Abfrage zählt die Anzahl der Punkte, die sowohl einen größeren Theta-Wert als auch einen größeren Radius haben als ein bestimmter Punkt.

Gibt es eine Möglichkeit, dies schneller oder lesbarer zu schreiben?

Antworten
13
Ist dies eine Linq-zu-SQL-Abfrage oder eine Linq-zu-Objekten? Sean Lynch vor 9 Jahren 1
Dies ist linq für Objekte. mjcopple vor 9 Jahren 0
Wie bereits gesagt, ist Ihr Code in Ordnung. Ich bin nicht sicher, was Sie mit "Auswählen" meinen, wenn Sie sagen "Ich wähle alle Punkte" aus? Dass Sie alle durchlaufen? Sie können sie nicht zählen, ohne sie zu durchlaufen, also ist das in Ordnung. Oder denken Sie, dass Ihre linq-Abfrage ein temporäres Array erstellt, für das Sie dann Count aufrufen? Es tut nicht sepp2k vor 9 Jahren 1

4 Antworten auf die Frage

9
Anthony Pegram

Zunächst wird Ihre Anfrage gut geschrieben. Ihre Struktur ist kein Anliegen. Die Reihenfolge der Froms ist eindeutig korrekt, die Auswahl ist angemessen. Wo Sie nach Verbesserungen suchen könnten, die die Abfrage ändern könnten (Code und möglicherweise Leistung), würde sich in der GetDataMethode befinden. Wenn zum Beispiel GetDatawird immer Daten von einer externen, abfragbaren Quelle, dann können Sie die Filterung abzuladen es nicht alle Datenpunkte bekommen und Filterung es in Ihrer Anwendung, vor allem, da Sie so viele Punkte von Daten ( möglicherweise). Vielleicht könnte Ihre Frage also stattdessen sein

(from type in ValidTypes()    
 select GetData(type, referencePoint).Count())
.Sum();

// or same meaning, different phrasing

(from type in ValidTypes()
from point in GetData(type, referencePoint)
select point).Count();
7
Homde

Warum tust du:

Point.Radius > referencePoint.Radius && point.Theta > referencePoint.Theta

IsCorrectReferencePointAnscheinend sollte dies wahrscheinlich eine Funktion sein oder so. Dadurch wird Ihr Code sowohl lesbarer als auch verständlicher, da Sie einfach den Funktionsnamen ansehen können, um zu sehen, was er tut.

Vergewissern Sie sich, dass es sich bei der Funktion um ein ordnungsgemäßes Predicate <> handelt, sodass sie bei der Überladung von .Count () wie in Martins Antwort verwendet werden kann. Snowbody vor 6 Jahren 0
3
Marty Neal

Dies ist eine alte Frage, aber vielleicht lohnt es sich, daran zu erinnern, dass .Count () eine nützliche Überlastung hat. Wenn Sie die Abfrage in fließender Syntax umschreiben, können Sie Folgendes schreiben:

int count = ValidTypes()
    .SelectMany(type => GetData(type))
    .Count(point => point.Radius > referencePoint.Radius 
                 && point.Theta > referencePoint.Theta);
2
Jay Bazuzi

Ich mag es nicht, eine Aussage zu schreiben, die sowohl die "fließende" als auch die "Ausdruck" -Syntax für LINQ kombiniert. (Siehe SO: Welche LINQ-Syntax bevorzugen Sie? Fließend oder Abfrageausdruck )

Ich würde auch mehrere whereKlauseln über eine wheremit auswählen &&. Also entweder:

var points = from type in ValidTypes()
    from point in GetData(type)
    where point.Theta > referencePoint.Theta
    where point.Radius > referencePoint.Radius
    select point;

var count = points.Count();

oder

var count = ValidTypes
    .Select(type => type.GetData())
    .Where(point.Theta > referencePoint.Theta)
    .Where(point.Radius > referencePoint.Radius)
    .Count();

Ich würde mir den Code vorher und nachher ansehen und schauen, ob sich einer von ihnen für weiteres Refactoring eignet.