42

I have a list of objects and I am trying to remove a specific object in the list by first checking a property in the object.

Originally I used a foreach but then realised you can't use this while modifying a collection, so I decided to use a normal for but then I'm not sure how to write code that does what I originally wrote.

How do I go about writing code to do what I originally had?

Thanks

Here's my code:

    public void DeleteChunk(int ChunkID)
    {
        //foreach (Chunk i in ChunkList)
        //{
        //    if (i.UniqueID == ChunkID)
        //    {
        //        ChunkList.Remove(i);
        //    }
        //}

        //This won't work because here i is just an integer so i.UniqueID won't exist.
        for (int i = 0; i < ChunkList.Capacity; i++)
        {
            if (i.UniqueID == ChunkID)
            {
                ChunkList.Remove(i);
            }
        }

    }
user9993
  • 5,833
  • 11
  • 56
  • 117

11 Answers11

105

You can simplify this with linq:

var item = ChunkList.SingleOrDefault(x => x.UniqueId == ChunkID);
if (item != null)
    ChunkList.Remove(item);

You can also do the following, which will also work if there is more than one match:

ChunkList.RemoveAll(x => x.UniqueId == ChunkID);
Khan
  • 17,904
  • 5
  • 47
  • 59
19

You're removing and then incrementing, which means you'll be one ahead of yourself. Instead, remove in reverse so you never mess up your next item.

for (int i = ChunkList.Count-1; i >=0; i--)
{
    if (ChunkList[i].UniqueID == ChunkID)
    {
        ChunkList.RemoveAt(i);
    }
}
bland
  • 1,968
  • 1
  • 15
  • 22
  • This does not work, because I get "The best overload method for... has some invalid arguments" when I hover over ChunkList.Remove(i) – user9993 Sep 20 '13 at 13:22
  • @0x4C4A41 You need to provide the type of collection that ChunkList is in order to ensure we provide correct help. Otherwise, we can only guide you so far. – bland Sep 20 '13 at 13:24
  • 1
    Try `ChunkList.RemoveAt(i)` – Khan Sep 20 '13 at 13:24
  • private List ChunkList = new List(); Chunk being a class with some properties in it. ChunkList.RemoveAt seems to work thanks – user9993 Sep 20 '13 at 13:26
11

If ChunkList is List<Chunk>, you can use the RemoveAll method:

ChunkList.RemoveAll(chunk => chunk.UniqueID == ChunkID);
Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
7

First you have to find out the object in the list. Then you can remove from the list.

       var item = myList.Find(x=>x.ItemName == obj.ItemName);
       myList.Remove(item);
vasily.sib
  • 3,871
  • 2
  • 23
  • 26
vivek
  • 248
  • 3
  • 6
3

Originally I used a foreach but then realised you can't use this while modifying a collection

You can create a copy of the collection and iterate over that using ToList() to create to copy:

 foreach(Chunk chunk in ChunkList.ToList())
 {
     if (chunk.UniqueID == ChunkID)
     {
         ChunkList.Remove(chunk);
     }
 }
DGibbs
  • 14,316
  • 7
  • 44
  • 83
2

There are two problems with this code:

  • Capacity represents the number of items the list can contain before resizing is required, not the actual count; you need to use Count instead, and
  • When you remove from the list, you should go backwards, otherwise you could skip the second item when two identical items are next to each other.
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

You're checking i's UniqueID while i is actually an integer. You should do something like that, if you want to stay with a for loop.

for (int i = 0; i < ChunkList.Capacity; i++)
{
    if (ChunkList[i].UniqueID == ChunkID)
    {
        ChunkList.Remove(i);
    }
}

You can, and should, however, use linq:

ChunkList.Remove(x => x.UniqueID == ChunkID);
Raz Harush
  • 739
  • 1
  • 6
  • 21
2

Firstly, you are using Capacity instead of Count.

Secondly, if you only need to delete one item, then you can happily use a loop. You just need to ensure that you break out of the loop after deleting an item, like so:

int target = 4;

for (int i = 0; i < list.Count; ++i)
{
    if (list[i].UniqueID == target)
    {
        list.RemoveAt(i);
        break;
    }
}

If you want to remove all items from the list that match an ID, it becomes even easier because you can use List<T>.RemoveAll(Predicate<T> match)

int target = 4;

list.RemoveAll(element => element.UniqueID == target);
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
1

One technique is to create a copy of the collection you want to modify, change the copy as needed, then replace the original collection with the copy at the end.

1

You can use a while loop to delete item/items matching ChunkID. Here is my suggestion:

public void DeleteChunk(int ChunkID)
{
   int i = 0;
   while (i < ChunkList.Count) 
   {
      Chunk currentChunk = ChunkList[i];
      if (currentChunk.UniqueID == ChunkID) {
         ChunkList.RemoveAt(i);
      }
      else {
        i++;
      }
   }
}
knguyen
  • 119
  • 2
  • 8
0

Simplest solution without using LINQ:

    Chunk toRemove = null;
    foreach (Chunk i in ChunkList)
    {
        if (i.UniqueID == ChunkID)
        {
            toRemove = i;
            break;
        }
    }
    if (toRemove != null) {
        ChunkList.Remove(toRemove);
    }

(If Chunk is a struct, then you can use Nullable<Chunk> to achieve this.)

knocte
  • 16,941
  • 11
  • 79
  • 125