views:

240

answers:

4

Hi guys!

I need to iterate through a LinkedList<T> (in .NET 2.0) and remove all the items according to a given criteria. It was easy way under Java, since I could do the following:

Iterator<E> i = list.iterator();
while (i.hasNext()) {
    E e = i.next();
    if (e == x) {
        // Found, so move it to the front,
        i.remove();
        list.addFirst(x);
        // Return it
        return x;
    }
}

Unfortunately, in the .NET behavior of IEnumerator<T> (the equivalent of Iterator<E>) there's no remove method to remove the current element from the collection. Also, in the LinkedList<T> there's no way to access an element at a given index, to accomplish the task by iterating back from the last to the first.

Have you got any idea on how to do it? Thank you very much!

+1  A: 

It's actually a lot easier in C#.

function PlaceAtHead(<T> x)
{
   list.Remove(x);
   list.AddFirst(x);
   return x;
}
Kris Erickson
It's not what the OP asked...
Thomas Levesque
This has nothing to do with the question...
ShaneC
I haven't tried it yet, but I believe this will rise an exception, because of the open Enumerator...
Antonello
This just does exactly what Antonello code snippet does. You cannot remove an item while you are enumerating through it, however .Net does allow you to just remove items without having to enumerate to find them. The standard solution to remove items from a .Net list of any kind is to build up a second list of Remove items and them remove them after the enumerator has finished, this just simplifies that.
Kris Erickson
+1, works for the OP's example and otherwise, will work if you find the item to remove first.
Meta-Knight
+1  A: 

One ugly option is to iterate through your list, find all the items that apply and store them in a list. Then iterate through your second list and call remove on your LinkedList...

I'm hoping someone else has a more elegant solution :)

ShaneC
I actually quite like that idea ...
Unsliced
That's what I thought also, but, elegance apart, it could not work in every condition, since 2 nodes of the list might be equal...
Antonello
I put a one pass version down below, that will handle duplicates as well. It's based on using LinkedList<T>.Remove(LinkedListNode<T>)
Reed Copsey
+6  A: 

This will remove all nodes that match a criteria, in one loop through the linked list.

LinkedListNode<E> node = list.First;

while (node != null)
{
    var next = node.Next;
    if (node.Value == x) {
        list.Remove(e);
    }
    node = next;
}

I believe that's what you're attempting... You also added back in the node at the beginning of the list (so your java code didn't remove all of the nodes, but rather moved the first matching to the beginning of the list). That would be easy to do with this approach, as well.

Reed Copsey
A: 

Just a little addition to Reed Copsey's answer with a predicate:

    public static T MoveAheadAndReturn<T>(LinkedList<T> ll, Predicate<T> pred)
    {
        if (ll == null)
            throw new ArgumentNullException("ll");
        if (pred == null)
            throw new ArgumentNullException("pred");


        LinkedListNode<T> node = ll.First;
        T value = default(T);

        while (node != null)
        {
            value = node.Value;
            if (pred(value))
            {
                ll.Remove(node);
                ll.AddFirst(node);
                break;
            }
            node = node.Next;
        }

        return value;
    }
bruno conde