-1

The code throws an error with reason as we easily see.

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

But there must be a way to do that, with foreach (not for), with using List<>. Please do not tell me Deep Copy methods like making

var cloneList = NumberList.ToList()

and removing item from it. Because if we have 1 million elements, we will make it 2 million for removing etc. I don't need this.

The code snippet is here;

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

Please help me about this brain burner code snippet..

Thank you.

UPDATE : The question is not about getting Sum() of the List elements at the final point. The core of question is, how to remove item from list while foreach looping.

Kuthay Gumus
  • 764
  • 3
  • 12
  • 30

5 Answers5

0

You are modifieng your collection inside the foreach loop so in next iteration the collection element number change and foreach fail to iterate, try this

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);
}
Mostafiz
  • 7,243
  • 3
  • 28
  • 42
  • This makes deep copy my friend. Derivates new List from our first List and removes from second list. This is not what i'm looking for. And you should use ToList() to make your code work but that is not i'm looking for. Thx. – Kuthay Gumus May 04 '16 at 08:00
0

First calculate the totals and then remove the items:

var totals = numberList.Sum();  
numberList.RemoveAll(i=>i==5);
Alex Art.
  • 8,711
  • 3
  • 29
  • 47
  • Thanks for the answer, It takes you to the result, I know that but can you read the update please ? My point is not that.. Sorry for late update mate. – Kuthay Gumus May 04 '16 at 07:51
0

If the double iteration and deep copy is the problem here is my approach:

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

or

    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;
    }
ntohl
  • 2,067
  • 1
  • 28
  • 32
  • First, thanks for the answer. But, when you debug, you will see numberList still contains 9 elements mate. I need to remove 5th element and than take the count while i'm still using the original list. How can we do that ? – Kuthay Gumus May 04 '16 at 12:02
  • You might use the `YieldingNotFive(numberList)` for the rest of the function. It's local variable. But the honest answer is I don't know how should You remove from the iterated list, while being iterated. – ntohl May 04 '16 at 12:05
  • thanks for the answer mate, i will share when i get the answer from mvp :) – Kuthay Gumus May 04 '16 at 12:15
0

Try to add a counter for a loop and when arrived in your condition remove the element.

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

But i don't know the name of the functions for remove from index.

Morker
  • 1
  • 3
0

I found the answer. From the below you can see the performance detail between tradinional foreach and Parallel.ForEach.

I hope this will be useful.

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();
    }
}
Kuthay Gumus
  • 764
  • 3
  • 12
  • 30
  • Why on earth would you do this - you essentially iterating the loop twice, just on different threads. Its effectively the same as taking a copy of the collection and is twice the work of a `for` loop. –  May 05 '16 at 07:14