LINQ on a LinkedList - iterate over LinkedListNode<T>, not T
I'm having a problem understanding how to do someth开发者_StackOverflow社区ing in LINQ.
I have a linkedlist, the type of the object doesn't matter. What does matter is that I want to do something in a Where()
based on the relationship between the current object and the next one in the list.
Why can't I do something like:
linkedlist.Where(n=>a_function(n.Value, n.Next.Value))
?
What is the syntax to do this, if it's even possible? The type inference system seems to insist that I want the lambda argument to be T
, not LinkedListNode<T>
.
You'll have to write new iterator for linked list to do that. Something like
public static class LinkedListExtensions
{
public static IEnumerable<LinkedListNode<T>> EnumerateNodes<T>(this LinkedList<T> list)
{
var node = list.First;
while(node != null)
{
yield return node;
node = node.Next;
}
}
}
so you can use
linkedlist.EnumerateNodes().Where(n=>a_function(n.Value, n.Next.Value))
Your issue doesn't have much to do with type-inference; LinkedList<T>
is an IEnumerable<T>
, not an IEnumerable<LinkedListNode<T>>
. Additionally, there isn't a direct way to get a sequence of (current, next)
tuples, so you'll have to implement that yourself.
Here's one (not so efficient) way with LINQ:
var filtered = linkedlist.Zip(linkedList.Skip(1),(current, next) => new {current, next} )
.Where(a => a_function(a.current, a.next))
.Select(a => a.current);
This will choose a value if the predicate matches (value, nextValue)
. You might have to tweak the query a bit if that isn't exactly what you need.
Otherwise, go with max's solution if you need efficiency or if you have lots of filters that are based on (node, nextNode)
.
Inspired by max's answer, I came up with a shorter version:
public static IEnumerable<LinkedListNode<T>> GetNodes<T>(this LinkedList<T> list)
{
for (var node = list.First; node != null; node = node.Next)
yield return node;
}
Or you could sacrifice readability for an even shorter version:
public static IEnumerable<LinkedListNode<T>> GetNodes<T>(this LinkedList<T> list)
=> for (var node = list.First; node != null; node = node.Next) yield return node;
精彩评论