What you are looking for is the filter concept. C# does provide an application of such a concept for lists, however it gets complicated if you aren't just trying to filter on the attributes of the object. Microsoft makes the filitering capability generic accross C# with LINQ See this post, or this post for an example:
Filtering collections in C#
Basically the syntax is :
var newlist = list.linqquery1.linquery2...linqueryN.Where(s.x condition);
of course if its simple enough you can do the following:
var newlist = list.Where(s.x condition);
But your problem also calls for selection based on subsequent items in the list. This is a whole lot more complicated because you won't be able to access those elements unless you attach that data to the element in the list. For example, if your listelem
was actually a doubly linked list node, you could look ahead in the list for elements after ward based only on a forward node reference and run a condition like this (to check if two green cars follow):
var green2follows = carlist.Where(s.next.type == greencar && s.next.next.type == greencar);
You could, however, concieve of a situation in which it wouldn't be necesary to use doubly linked lists if you implimented this yourself with iteration. Unfortunately, because LINQ works primarily on enumeration based queries, you have to find work around to use Microsofts built in utilities for filtering (though this is not unique to microsoft, typically you don't include locality in queries) This post covers that conclusion.
To do this iteratively, you would create a for loop and test against i + 1, and i + 2 values of cars. Be carful as this gets messy with previous values (i - n) Iterators might be good for this to avoid errors, though i'm not sure if c# supports iterator arithmetic like other languages to allow you to go backwards and forwards. You may be forced to make a custom iterator to generically define this kind of filter.
EDIT: you can avoid creating a custom iterator and merely create a custom object returned by the iterator that supports forward and backward looking via iterator blocks (like the answer suggest in this post)
What you might do is something like this:
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);
}
}
Instead of using your list and LINQing over that, use this iterator instead templated on your list, this way you don't have to deal with nasty iterator semantics in C# for creating your own whilist still being able to implement all the functionality you would need to go over the list.
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()
};
The reason you would include i
and the list itself in the HandleObject
constructor is to allow for forward and backward searching through the list based on the position i
passed in.