Deleting items from a ArrayList

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

This is a little problem that has been driving me nuts. I have an ArrayList
of objects, and I want to delete all the objects that satisfy some condition:

foreach (MyObject myObject in ObjectList)
{
if (MyObject.DeleteCondition())
{
ObjectList.Remove(myObject);
}
}

This of course doesn't work because the deletion messes up the iteration and
an exception is thrown. The only way I've managed to do this is:

ArrayList ToBeDeleted = new ArrayList();
foreach (MyObject myObject in ObjectList)
{
if (MyObject.DeleteCondition())
{
ToBeDeleted.Add(myObject);
}
}
foreach (MyObject myObject in ToBeDeleted)
{
ObjectList.Remove(myObject);
}

This seems awfully ham-fisted and I can't help thinking there must be a more
elegant way of doing it. Any suggestions?
 
...
This is a little problem that has been driving me nuts.
I have an ArrayList of objects, and I want to delete all
the objects that satisfy some condition:

foreach (MyObject myObject in ObjectList)
{
if (MyObject.DeleteCondition())
{
ObjectList.Remove(myObject);
}
}

This of course doesn't work because the deletion
messes up the iteration and
an exception is thrown.

int len = ObjectList.Count;
MyObject myObject = null;
for (int i = len -1; i >= 0; i--)
{
myObject = (MyObject) ObjectList;

if (MyObject.DeleteCondition())
{
ObjectList.Remove(myObject);
}
}

Note the reversed iteration...


// Bjorn A
 
...
This is a little problem that has been driving me nuts.
I have an ArrayList of objects, and I want to delete all
the objects that satisfy some condition:

foreach (MyObject myObject in ObjectList)
{
if (MyObject.DeleteCondition())
{
ObjectList.Remove(myObject);
}
}

This of course doesn't work because the deletion
messes up the iteration and
an exception is thrown.

int len = ObjectList.Count;
MyObject myObject = null;
for (int i = len -1; i >= 0; i--)
{
myObject = (MyObject) ObjectList;

if (MyObject.DeleteCondition())
{
ObjectList.Remove(myObject);
}
}

Note the reversed iteration...


Actually, this would be "safer", if there could be more than one reference
to the same object within the list...

int len = ObjectList.Count;
MyObject myObject = null;
for (int i = len -1; i >= 0; i--)
{
myObject = (MyObject) ObjectList;

if (MyObject.DeleteCondition())
{
ObjectList.RemoveAt(i);
}
}

// Bjorn A
 
OK, yes, that should work, and is slightly more elegant. All we need now is a
reverse implementation of foreach!
 
Do a reverse iteration & remove the object
eg

for(int i = ar.Count - 1; i >= 0; i--)
{
object myObject = ObjectList;
if (myObject.DeleteCondition)
ObjectList.Remove(myObject);
}


HTH
Kalpesh
 
Dave said:
This is a little problem that has been driving me nuts. I have an ArrayList
of objects, and I want to delete all the objects that satisfy some condition:

foreach (MyObject myObject in ObjectList)
{
if (MyObject.DeleteCondition())
{
ObjectList.Remove(myObject);
}
}

This of course doesn't work because the deletion messes up the iteration and
an exception is thrown. The only way I've managed to do this is:

ArrayList ToBeDeleted = new ArrayList();
foreach (MyObject myObject in ObjectList)
{
if (MyObject.DeleteCondition())
{
ToBeDeleted.Add(myObject);
}
}
foreach (MyObject myObject in ToBeDeleted)
{
ObjectList.Remove(myObject);
}

This seems awfully ham-fisted and I can't help thinking there must be a more
elegant way of doing it. Any suggestions?

I call this particular solution "Death Row" or "The Hit List".
It is not particularly elegant , but it does work.

Personally I would like a built in mechanism for removal that does not invalidate the iterator.
Maybe something built into Collections where you pass in a predicate to determine removal criteria.
I would also like to see a version of "foreach" that takes a predicate so that foreach could act on
a subset of the data in the collection.

Anyway, just my 2 cents
Bill
 
THis is a bit long, as it's the complete working code (including test
harness), but the remove algorithm will prove to be the fastest on large
ArrayLists:

public static void Main()
{
ArrayList ObjectList = new ArrayList();
ObjectList.Add(1);
ObjectList.Add(2);
ObjectList.Add(3);
ObjectList.Add(4);
ObjectList.Add(5);
ObjectList.Add(6);
ObjectList.Add(7);

int good = 0;
int pos = 0;
while (pos < ObjectList.Count)
{
if (!DeleteCondition(ObjectList[pos]))
{
if (good < pos)
ObjectList[good] = ObjectList[pos];
good++;
}

++pos;
}
ObjectList.RemoveRange(good, ObjectList.Count - good);
foreach(int i in ObjectList)
Console.WriteLine(i);

Pause();
}

static bool DeleteCondition(object test)
{
int t = (int) test;
return (t /2.0) == (t/2); // true for even numbers
}


The thing to note here is that each time you call ArrayList.Remove, it
shifts every item after the deleted item. In other words,
ObjectList.Remove(0) by itself is doing about as much work as my entire
algorithm remove all of them.
--
Truth,
James Curran
[erstwhile VC++ MVP]

Home: www.noveltheory.com Work: www.njtheater.com
Blog: www.honestillusion.com Day Job: www.partsearch.com
 
Back
Top