Was Sie suchen, ist das Filter Konzept. C# bietet eine Anwendung eines solchen Konzepts für Listen, es wird jedoch kompliziert, wenn Sie nicht nur versuchen, die Attribute des Objekts zu filtern. Microsoft macht die filitering Fähigkeit generic accross C# mit LINQthis post See, oder this post für ein Beispiel:
Filtering collections in C#
Grundsätzlich ist die Syntax:
var newlist = list.linqquery1.linquery2...linqueryN.Where(s.x condition);
natürlich, wenn seine einfach genug, um Sie das tun können, folgende:
var newlist = list.Where(s.x condition);
Aber Ihr Problem fordert auch selec basierend auf nachfolgenden Punkten in der Liste. Das ist sehr viel komplizierter, weil Sie nicht auf diese Elemente zugreifen können, wenn Sie diese Daten nicht an das Element in der Liste anhängen. Wenn Ihr listelem
beispielsweise ein doubly linked list-Knoten ist, könnten Sie in der Liste für Elemente nach Station nur auf einer Vorwärtsknoten-Referenz basieren und eine Bedingung wie diese ausführen (um zu prüfen, ob zwei grüne Autos folgen):
var green2follows = carlist.Where(s.next.type == greencar && s.next.next.type == greencar);
Sie könnten jedoch von einer Situation ausgehen, in der es nicht notwendig wäre, doppelt verkettete Listen zu verwenden, wenn Sie dies selbst mit Iteration iteriert haben. Da LINQ hauptsächlich auf aufzählungbasierten Abfragen arbeitet, müssen Sie leider eine Umgebung finden, in der Microsofts integrierte Dienstprogramme zum Filtern verwendet werden (obwohl dies nicht für Microsoft typisch ist, in der Regel enthalten Sie keinen Ort in Abfragen). This post deckt diese Schlussfolgerung ab.
Um dies iterativ zu tun, würden Sie eine for-Schleife erstellen und gegen i + 1 und i + 2 Werte von Autos testen. Seien Sie vorsichtig, da dies mit früheren Werten unordentlich wird (i - n) Iteratoren könnten dafür gut sein, um Fehler zu vermeiden, obwohl ich nicht sicher bin, ob C# Iteratorarithmetik wie andere Sprachen unterstützt, damit Sie rückwärts und vorwärts gehen können. Möglicherweise müssen Sie einen benutzerdefinierten Iterator erstellen, um diese Art von Filter generisch zu definieren.
EDIT: können Sie vermeiden, eine benutzerdefinierte Iterator erstellen und lediglich erstellen benutzerdefinierte Objekt vom Iterator zurückgegeben, die vorwärts und rückwärts schaut über Iterator Blöcke (wie die answer suggest in this post)
unterstützt Was Sie vielleicht ist so etwas wie dies:
HandleObject<T>...
...
public bool backwardsWhere(condition)...
public bool forwardsWhere(condition)...
public bool backwardsNWhere(n, condition);
public bool forwardsNWhere(condition);
//other forwards filter functions for convienience
// get back the element that we wraped
public T get();
static IEnumerable<T> iteratorBlock(List<T> list)
{
foreach (int i = 0; i < list.Length; i++)
{
// yield means a new HandleObject is only created upon access, and
// need not be stored otherwise
yield return HandleObject<T>(i, list);
}
}
statt Ihre Liste und Linqing gegenüber der Verwendung, benutzen Sie diesen Iterator stattdessen auf Ihrer Liste als Templat, auf diese Weise können Sie Ihre eigenen nicht mit fieser Iterator Semantik in C# zu tun haben für die Erstellung von whilist noch sein in der Lage, al l Die Funktionalität, die Sie benötigen, um über die Liste zu gehen.
var customIterableFromBlock = iteratorBlock<Car>(carlist);
var selectedCars = from handleCar in customIterableFromBlock
where ... //handleCar.backwardsWhere(...)&& handleCar.forwardsWhere(...)
//handleCar.get().x == condition etc
select Car
{
//get Car from handleCar.get()
};
Der Grund, warum Sie i
und die Liste selbst in den HandleObject
Konstruktor umfassen würde, ist für Vorwärts- und Rückwärtssuche durch die Liste basierend auf der Position zu ermöglichen i
eingeleitet.
Ich bin nicht bekannt, dass Bibliotheken, die dies tun, aber Sie könnten vielleicht eine 'toString()' Methode für das Objekt definieren und stattdessen Regex darauf ausführen. Ich versuche mir das als eine Linq-Abfrage vorzustellen (vorausgesetzt, Sie hatten irgendeine Art von Ordnung in das Objekt eingebaut) und ich muss mir vorstellen, dass das auch wirklich hässlich aussieht. –
@EdPlunkett nicht einmal in der Nähe eines Duplikats von diesem. Diese Frage fragt *, * worüber sie tatsächlich sprechen, es gibt Leute, die nicht einmal wissen, dass LINQ existiert, und dies deshalb als Duplikat zu markieren, wäre kontraproduktiv. – snb
@dasblinkenlight Ich habe mich sehr stark auf LINQ verlassen, um teilweise nach sehr spezifischen Mustern zu suchen, aber es ist nichts, was ich als die Lösung betrachte, nach der ich suche (es sei denn, ich habe etwas offensichtlich übersehen). Können Sie einen LINQ-Ausdruck schreiben, der eines der von mir bereitgestellten Beispielmuster löst? – stevcode