45

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

    }
3
  • 1
    "This won't work" is not a good description of what goes wrong. Commented Sep 20, 2013 at 13:14
  • What type is ChunkList? Commented Sep 20, 2013 at 13:14
  • 4
    Remember Capacity and Count are different and may not be the same. Commented Sep 20, 2013 at 13:15

11 Answers 11

109

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);
Sign up to request clarification or add additional context in comments.

5 Comments

But for list there is no Remove(Predicate), it needs to be RemoveAll()
x.UniqueID does not have an extension method, apparently.
Do you mean ChunkList? What type is ChunkList?
private List<Chunk> ChunkList = new List<Chunk>(); Chunk being a class with some properties in it.
The above should work then. Are you sure you have the syntax correct?
20

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

4 Comments

This does not work, because I get "The best overload method for... has some invalid arguments" when I hover over ChunkList.Remove(i)
@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.
Try ChunkList.RemoveAt(i)
private List<Chunk> ChunkList = new List<Chunk>(); Chunk being a class with some properties in it. ChunkList.RemoveAt seems to work thanks
11

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

ChunkList.RemoveAll(chunk => chunk.UniqueID == ChunkID);

Comments

9

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

2 Comments

First you have to find out the object in the list. Then you can remove from the list.
do we need to implement IEquatable for this to work? or does it just compare reference?
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);
     }
 }

Comments

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.

Comments

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

Comments

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

Comments

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.

Comments

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

Comments

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.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.