How to iterate over a list while deleting items?

I am trying to find an elegant way to iterate over a list while items are deleted at the same time. I know this solution . But my conditions are something more complex:

  • all single threaded here
  • Iteration should be forward .
  • Each item must be processed exactly once .
  • Multiple and random items can be deleted while 1 item is being processed.
  • Elements are complex and intelligent objects. They execute their own method and can decide that some elements (from 0 to all) should be removed.
  • (adding and pasting can also happen, but right now it doesn't matter if there is a way to handle this at the same time, that would be great)

Question: Is this possible? If so, how?


I have the idea of marking objects as remote / inactive. When I repeat later, I will remove them without telling them to do something. The iteration will be repeated quite often, so each object must have exactly 1 revolution at each iteration. Will this work?


This is how I understand now. This is not perfect, but it gives you a clue what I hope for.

Pseudo Code:

class Foo
{
    public void DoStuff()
    {
        // do other stuff

        if (condition)
            Kill(x); // should result in list.RemoveAt(x) somehow
    }
}

class Program
{
    [STAThread]
    static void Main(string[] args)
    {
        List<Foo> list = new List<Foo>();
        for (int i = 0; i < 15; i++)
            list.Add(new Foo());

        for (int i = 0; i < list.Count; i++)
            list[i].DoStuff();

        Console.ReadKey();
    }
}


(This is not XY's problem. I’m sure it’s been sitting on my mind for many years, and I finally decided to find a lasting solution. I work in C # for this. This is not a joke. Sorry if I like the seams.)

Thanks for any help!

+4
2

, ObservableCollection , , , , . ObservableCollection, , , , .

public static IEnumerable<T> IterateWhileMutating<T>(
    this ObservableCollection<T> list)
{
    int i = 0;
    NotifyCollectionChangedEventHandler handler = (_, args) =>
    {
        switch (args.Action)
        {
            case NotifyCollectionChangedAction.Add:
                if (args.NewStartingIndex <= i)
                    i++;
                break;
            case NotifyCollectionChangedAction.Move:
                if (args.NewStartingIndex <= i)
                    i++;
                if (args.OldStartingIndex <= i) //note *not* else if
                    i--;
                break;
            case NotifyCollectionChangedAction.Remove:
                if (args.OldStartingIndex <= i)
                    i--;
                break;
            case NotifyCollectionChangedAction.Reset:
                i = int.MaxValue;//end the sequence
                break;
            default:
                //do nothing
                break;
        }
    };
    try
    {
        list.CollectionChanged += handler;
        for (i = 0; i < list.Count; i++)
        {
            yield return list[i];
        }
    }
    finally
    {
        list.CollectionChanged -= handler;
    }
}

. , .

+6

/.

, , . , . :

var toRemove = new HashSet<Item>();

foreach (var item in list)
{
    toRemove.UnionWith(item.GetItemsToRemove());
}

list.RemoveAll(item => toRemove.Contains(item));

, (O (n)), List<T> O (n), ().

+3

All Articles