LinkedList上的LINQ - 迭代LinkedListNode <t>,而不是T </t>

时间:2010-10-23 12:12:40

标签: .net linq linked-list

我在理解如何在LINQ中执行某些操作时遇到问题。

我有一个链表,对象的类型无关紧要。重要的是我想根据当前对象与列表中下一个对象之间的关系在Where()中做一些事情。

为什么我不能做类似的事情:

linkedlist.Where(n=>a_function(n.Value, n.Next.Value))

如果可能的话,执行此操作的语法是什么?类型推断系统似乎坚持我希望lambda参数为T,而不是LinkedListNode<T>

3 个答案:

答案 0 :(得分:15)

你必须为链表创建新的迭代器才能做到这一点。像

这样的东西
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;
        }
    }
}

所以你可以使用

linkedlist.EnumerateNodes().Where(n=>a_function(n.Value, n.Next.Value))

答案 1 :(得分:2)

您的问题与类型推断没有多大关系; LinkedList<T>IEnumerable<T>,而不是IEnumerable<LinkedListNode<T>>。此外,没有直接方法来获取(current, next)元组的序列,因此您必须自己实现它。

这是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);

如果谓词与(value, nextValue)匹配,则会选择一个值。如果这不完全符合您的需要,您可能需要稍微调整一下查询。

否则,如果您需要效率或者有许多基于(node, nextNode)的过滤器,请使用max的解决方案。

答案 2 :(得分:0)

受max答案的启发,我想出了一个简短的版本:

public static IEnumerable<LinkedListNode<T>> GetNodes<T>(this LinkedList<T> list)
{
    for (var node = list.First; node != null; node = node.Next)
        yield return node;
}

或者您可以为更短的版本牺牲可读性:

public static IEnumerable<LinkedListNode<T>> GetNodes<T>(this LinkedList<T> list)
    => for (var node = list.First; node != null; node = node.Next) yield return node;
相关问题