Reputation: 6180
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);
}
}
}
Upvotes: 44
Views: 224504
Reputation: 268
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);
Upvotes: 9
Reputation: 17979
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.)
Upvotes: 0
Reputation: 119
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++;
}
}
}
Upvotes: 1
Reputation: 109852
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);
Upvotes: 2
Reputation: 2004
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);
}
}
Upvotes: 20
Reputation: 18172
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);
Upvotes: 107
Reputation: 14618
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);
}
}
Upvotes: 3
Reputation: 739
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);
Upvotes: 2
Reputation: 38810
If ChunkList
is List<Chunk>
, you can use the RemoveAll
method:
ChunkList.RemoveAll(chunk => chunk.UniqueID == ChunkID);
Upvotes: 11
Reputation: 727067
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, andUpvotes: 2
Reputation:
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.
Upvotes: 1