如何在同时删除项目时迭代列表? [英] How to iterate over list while removing items at the same time?

查看:128
本文介绍了如何在同时删除项目时迭代列表?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种优雅的方式来迭代列表,同时删除项目。
我知道这个解决方案。但我的条件更难:

I'm trying to find an elegant way to iterate over a list while items are removed at the same time.
I know this solution. But my conditions are something harder:


  • 所有单线程此处

  • 迭代必须前进

  • 每件商品必须完全一次

  • 可以在处理1个项目时删除多个和随机项目。

  • 项目是复杂且智能的对象。他们执行一个自定义方法,它可以决定删除一些项目(0到all)。

  • (添加和插入也可以发生,但是现在这不重要,如果有办法同时处理这个问题,那就太好了)

  • all single-threaded here
  • Iteration must be forward.
  • Every item must be processed exactly once.
  • Multiple and random items can be removed while 1 item is being processed.
  • Items are complex and smart objects. They execute a custom method and it can decide that some items (0 to all) shall be removed.
  • (add and insert can happen too, but just now this is not important, in case there is a way to handle this at the same time, that would be great)

问题:这可能吗?如果是,怎么做?

Question: Is this possible ? If yes, how ?

我认为标记对象为已删除 / 无效。当我稍后再次迭代时,我会删除它们而不会让它们做任何事情。迭代将经常重复,这就是为什么每个对象在每次迭代时必须正好转1圈。那会有用吗?



这就是我现在处理的事情。它并不完美,但会给你提示我希望的提示。

I have the idea of marking the objects as removed / inactive. When I iterate again later, I will remove them without calling them to do things. The iteration will be repeated quite often, that's why every object must have exactly 1 turn at each iteration. Would that work ?


This is how I handle things now. It's not perfect but gives you the hint what is asked I hope.

伪代码:

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();
    }
}



(这不是一个XY问题。我很确定。我已经把这个放在我脑海里多年了,我决定最终找到一个可靠的解决方案。我正在用C#工作。这不是恶作剧。我是抱歉,如果它接缝那样。)

感谢您的帮助!

推荐答案

你可以做的是在这里使用 ObservableCollection ,这样迭代集合的代码就可以检测集合的时间和方式在迭代时发生变异。通过使用 ObservableCollection ,迭代代码可以在当前索引之前添加项目时递增索引,或者在当前索引之前删除项目时将其删除。

What you can do is use an ObservableCollection here so that the code that is iterating over the collection has a way of detecting when and how the collection is mutated while it is iterating. By using an ObservableCollection the iterating code can increment the index when an item is added before the current index, or decriment it when an item is removed from before the current index.

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;
    }
}

代码取自我的另一个答案。它包含有关在变异时迭代序列的后果的其他切向信息,以及关于此代码及其设计决策的含义的一些其他解释。

The code is taken from this other answer of mine. It contains additional tangential information about the consequences of iterating a sequence while mutating it, as well as some additional explanation about this code and the implications of its design decisions.

这篇关于如何在同时删除项目时迭代列表?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆