Martin Dzhonov
Martin Dzhonov

Reputation: 1081

c# how to get through every item in a list when using list.Remove

I have this code that has to remove all numbers from 1 to 700 containing digits bigger than 6

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Sevenland_Numbers
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> numbers = new List<string>();

            for (int i = 0; i <= 700; i++)
            {
                numbers.Add(i.ToString());

            }

            for (int i = 0; i <numbers.Count; i++)
            {
                if (numbers[i].Contains('7') || numbers[i].Contains('8') || numbers[i].Contains('9'))
                {
                    numbers.Remove(numbers[i]);
;
                }

            }
            for (int i = 0; i < numbers.Count; i++)
            {
                Console.WriteLine(numbers[i]);
            }


        }
    }
}

but when I use Remove the list gets resized so I don't get through all the elements with the for cycle. Is there an easy way to fix this ?

Upvotes: 2

Views: 87

Answers (4)

Magnus
Magnus

Reputation: 46919

Here is a simple way to do it:

var toRemove = "789";
numbers.RemoveAll(n => toRemove.Any(r => n.Contains(r)));

Upvotes: 5

rsbarro
rsbarro

Reputation: 27339

Just decrement the counter after you call Remove.

for (int i = 0; i <numbers.Count; i++)
{
    if (numbers[i].Contains('7') || numbers[i].Contains('8') || numbers[i].Contains('9'))
    {
        numbers.Remove(numbers[i]);
        i--;
    }
}

That will cause your loop to repeat the operation using the same value, and will keep it from "skipping" over the next value in the list.

Of course, you could always use LINQ as well:

var numbers = new List<string>();
for (var i = 0; i <= 700; i++)
    numbers.Add(i.ToString());

numbers = numbers
             .Where(n => !(n.Contains('7') || n.Contains('8') || n.Contains('9')))
             .ToList();

for (var i = 0; i < numbers.Count; i++)
    Console.WriteLine(numbers[i]);

Upvotes: 4

Adam Moszczyński
Adam Moszczyński

Reputation: 3556

normally i would use deleting loop:

for(int i = numbers.Count - 1; i > -1; --i){
    numbers.Remove(numbers[i])
}

Upvotes: 0

Petr Hudeček
Petr Hudeček

Reputation: 1763

There is.

Decrement the iterator index whenever you remove an element, like this:

 for (int i = 0; i <numbers.Count; i++)
 {
   if (numbers[i].Contains('7') || numbers[i].Contains('8') || numbers[i].Contains('9'))
   {
      numbers.Remove(numbers[i]);
      i--;
   }
 }

Alternatively, you may go through the list backwards (decrementing to 0):

 for (int i = numbers.Count-1; i >= 0; --)
 {
   if (numbers[i].Contains('7') || numbers[i].Contains('8') || numbers[i].Contains('9'))
   {
      numbers.Remove(numbers[i]);
   }
 }

That way, the math will handle itself out.

Upvotes: 2

Related Questions