【问题标题】:How to Remove Item Dynamically from List in Foreach Loop [duplicate]如何从 Foreach 循环中的列表中动态删除项目 [重复]
【发布时间】:2016-05-04 07:38:40
【问题描述】:

如我们所见,代码抛出错误是有原因的。

Error:{"Collection was modified; enumeration operation may not execute."}

但是必须有一种方法可以做到这一点,使用 foreach(而不是 for),使用 List。请不要告诉我Deep Copy之类的制作方法

var cloneList = NumberList.ToList()

并从中删除项目。因为如果我们有 100 万个元素,我们将使其成为 200 万个用于删除等。我不需要这个。

代码sn-p在这里;

public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        var numberList = new List<int>();
        numberList.AddRange(new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
        var totalNumber = 0;
        foreach (var item in numberList)
        {
            totalNumber += item;
            if (item == 5)
            {
                numberList.Remove(item);
            }
        }
        return View(totalNumber);
    }
}

请帮我了解一下这个烧脑代码 sn-p..

谢谢。

更新:问题不在于在最后一点获得列表元素的Sum()。问题的核心是,如何在 foreach 循环时从列表中删除项目。

【问题讨论】:

  • 使用for循环从最后一个循环到第一个
  • 我怀疑它是否允许您在迭代使用每个循环时删除项目。使用其他循环技术。
  • 你试过可以回答吗?
  • @StephenMuecke no for,没有回头路。我们必须在 foreach 循环并显示结果时这样做。
  • 这根本不可能。

标签: c# asp.net-mvc list foreach


【解决方案1】:

您正在 foreach 循环中修改您的集合,因此在下一次迭代中集合元素编号发生变化并且 foreach 无法迭代,试试这个

public ActionResult Index()
{
    var numberList = new List<int>();
    numberList.AddRange(new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
    var totalNumber = 0;
    var numberListTemp = numberList;
    foreach (var item in umberListTemp)
    {
        totalNumber += item;
        if (item == 5)
        {
            numberList.Remove(item);
        }
    }
    return View(totalNumber);
}

【讨论】:

  • 这让我的朋友深拷贝。从我们的第一个列表派生新列表并从第二个列表中删除。这不是我要找的。你应该使用 ToList() 来让你的代码工作,但这不是我想要的。谢谢。
【解决方案2】:

先计算总数,然后删除项目:

var totals = numberList.Sum();  
numberList.RemoveAll(i=>i==5);

【讨论】:

  • 感谢您的回答,它会将您带到结果,我知道,但是您能阅读更新吗?我的意思不是那个..抱歉更新晚了伙伴。
【解决方案3】:

如果双重迭代和深拷贝是我的方法:

        ...
        var numberList = new List<int>();
        numberList.AddRange(new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
        var totalNumber = 0;
        foreach (var item in YieldingNotFive(numberList))
        {
            totalNumber += item;
        }
        ...

    private IEnumerable<int> YieldingNotFive(List<int> numberList)
    {
        foreach (int item in numberList)
        {
            if (item != 5)
            {
                yield return item;
            }
        }
        yield break;
    }

    var numberList = new List<int>();
    numberList.AddRange(new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
    var totalNumber = 0;
    foreach (var item in numberList.Where(x => x != 5))
    {
        totalNumber += item;
    }

【讨论】:

  • 首先,感谢您的回答。但是,当您调试时,您会看到 numberList 仍然包含 9 个元素 mate。我需要删除第 5 个元素,而不是在我仍在使用原始列表时进行计数。我们该怎么做?
  • 您可以将YieldingNotFive(numberList) 用于该函数的其余部分。它是局部变量。但诚实的答案是,我不知道在被迭代时你应该如何从迭代列表中删除。
  • 感谢回答的小伙伴,当我得到mvp的答案时我会分享:)
【解决方案4】:

尝试为循环添加一个计数器,并在达到您的条件时删除该元素。

public class HomeController : Controller
{
    // GET: Home
    public ActionResult Index()
    {
        var numberList = new List<int>();
        numberList.AddRange(new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 });
        var totalNumber = 0;
        var count = 0;
        foreach (var item in numberList)
        {
            totalNumber += item;
            if (item == 5)
            {
                numberList.Remove(count);
            }
            count = count + 1;
        }
        return View(totalNumber);
    }
}

但我不知道从索引中删除的函数的名称。

【讨论】:

    【解决方案5】:

    我找到了答案。从下面您可以看到传统 foreach 和 Parallel.ForEach 之间的性能细节。

    我希望这会有用。

    class Program
    {
        static void Main(string[] args)
        {           
            List<string> colorList = new List<string>();
            colorList.AddRange(new List<string>() {
                                      "1. Red",
                                      "2. Green",
                                      "3. Blue",
                                      "4. Yellow",
                                      "5. White",
                                      "6. Black",
                                      "7. Violet",
                                      "8. Brown",
                                      "9. Orange",
                                      "10. Pink"
            });
            Console.WriteLine("Traditional foreach loop\n");
            //start the stopwatch for "for" loop
            var sw = Stopwatch.StartNew();
            foreach (string color in colorList)
            {
                Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(10);
            }
            Console.WriteLine("Foreach loop execution time = {0} seconds\n", sw.Elapsed.TotalSeconds);
    
            //-------------------------------------------------------------------------------------------------------------------------------------------------------
    
            Console.WriteLine("Using Parallel.ForEach");
            //start the stopwatch for "Parallel.ForEach"
            sw = Stopwatch.StartNew();
            int index = 0;
            Parallel.ForEach(colorList, (color, state) =>
            {
    
                ++index;
                if (index > colorList.Count - 1)
                {
                    state.Stop();
                }
    
                Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId);
                if (color == "2. Green")
                {
                    colorList.RemoveRange(3, 2);
                }
                Thread.Sleep(10);
            }
            );
            Console.WriteLine("Parallel.ForEach() execution time = {0} seconds", sw.Elapsed.TotalSeconds);
            Console.Read();
        }
    }
    

    【讨论】:

    • 你到底为什么要这样做——你实际上是在不同的线程上迭代循环两次。它实际上与获取集合的副本相同,并且是 for 循环的两倍。
    猜你喜欢
    • 2015-12-06
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-06-15
    • 2012-02-15
    • 2012-01-08
    相关资源
    最近更新 更多