469,336 Members | 5,552 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,336 developers. It's quick & easy.

Iterating through a HashTable

I have a hashtable keyed by some name, holding an instance of an object. Most
of the time I use the hashtable in the traditional sense, given a name, I
lookup the object, then I run a method on that object. Occaisionally however
I need to run a method on every object in the hashtable. I've done both
For..Each and iEnumeratior loops. The messy part is that under certain
conditions, while iterating, a condition exists where I need to remove an
object from the hashtable. With ArrayLists I handle this with a reverse
iteration (from last to first) and do a .RemoveAt. Hashtables do not have
..RemoveAt. For..Each doesnt work because .Remove needs the key and I only
have the object, iEnumerator doesn't work because I get an error after the
first .Remove saying my enumerator is now invalid, so I can't continue that
iteration.

I've thought about several solutions mostly inlvolving separate threads, but
wanted to know if there was a cleaner way to handle this. Anyone come across
this? It seems like a fairly standard problem, there must be some "pattern"
solution.
-Ken
Nov 21 '05 #1
10 14680
Try making a copy of the keys collection if it isn't too expensive.

Dim h As New Hashtable
Dim key, value As Object
Dim keys As ICollection = h.Keys
For Each key In keys
value = h(key)
If value.condition Then
h.Remove(key)
End If
Next

HTH
Nov 21 '05 #2
Uuhm... maybe actually making a copy would help.

Dim key, value As Object
Dim keys As ICollection = h.Keys
Dim keylist As New ArrayList
keylist.AddRange(keys)
For Each key In keylist
If CInt(key) > 5 Then
h.Remove(key)
End If
Next

"Jonas Pohlandt" <j.******************@dbit-systems.de> schrieb im
Newsbeitrag news:OE**************@tk2msftngp13.phx.gbl...
Try making a copy of the keys collection if it isn't too expensive.

Dim h As New Hashtable
Dim key, value As Object
Dim keys As ICollection = h.Keys
For Each key In keys
value = h(key)
If value.condition Then
h.Remove(key)
End If
Next

HTH

Nov 21 '05 #3
Ken,

I have the idea that you are not iterating through the keys of the
hasthtable but throught the values.

In my idea is that not where the hashtable is not made for, in that case by
instance the datatable does a much better job as collection because you have
much more methods to get the values from the objects in the datarow and
remove when needed those rows.

However maybe I see something wrong?

Cor
Nov 21 '05 #4
I've considered the copy solution, but given that I don't know in advance my
max item count, there'd be this potential baggage hanging over my head of a
duplicate collection. Also, because I'm using the 'value' side of the
hashtable, then based on some state need to delete it, I can't quite get the
logic in place even using a copy.

My solution so far is to do my iteration with a SyncLock wrapper and spawn a
separate thread for each 'Remove', then .NET will handle the blocking for me,
and the removes will occur after the iteration pass is complete. Or build an
array list of keys to delete as i'm iterating, and do a second for loop pass
on that array list. I was just hoping there was a way to get hash tables to
work the way i want inherintly.

"Jonas Pohlandt" wrote:
Uuhm... maybe actually making a copy would help.

Dim key, value As Object
Dim keys As ICollection = h.Keys
Dim keylist As New ArrayList
keylist.AddRange(keys)
For Each key In keylist
If CInt(key) > 5 Then
h.Remove(key)
End If
Next

"Jonas Pohlandt" <j.******************@dbit-systems.de> schrieb im
Newsbeitrag news:OE**************@tk2msftngp13.phx.gbl...
Try making a copy of the keys collection if it isn't too expensive.

Dim h As New Hashtable
Dim key, value As Object
Dim keys As ICollection = h.Keys
For Each key In keys
value = h(key)
If value.condition Then
h.Remove(key)
End If
Next

HTH


Nov 21 '05 #5
Well, I simplified my model for brevity. What I have is more complicated but
boils down to a hash table of open TCP sockets with the key being some
internal identifier. Normal processing is, given an identifier, I do
mySocket = myHashTable(identifier)
mySocket.send("blah")
again, this is simplified for example sake. it's not really like this there
is a lot of async calls and callbacks etc. Now, if I check and mySocket is
not connected, or if i get an error back from .send, I shutdown that socket
and remove it from the hashtable. When processing one at a time, this works
fine.

My problem is that there is one instance where I have to loop through the
entire hash table of sockets and do a .Send. In that instance, if i have a
bad socket and want to remove it from the Hashtable...i get the problem i
originally described. So, databases, etc. don't fit my problem domain.

-Ken

"Cor Ligthert" wrote:
Ken,

I have the idea that you are not iterating through the keys of the
hasthtable but throught the values.

In my idea is that not where the hashtable is not made for, in that case by
instance the datatable does a much better job as collection because you have
much more methods to get the values from the objects in the datarow and
remove when needed those rows.

However maybe I see something wrong?

Cor

Nov 21 '05 #6
Well, I simplified my model for brevity. What I have is more complicated but
boils down to a hash table of open TCP sockets with the key being some
internal identifier. Normal processing is, given an identifier, I do
mySocket = myHashTable(identifier)
mySocket.send("blah")
again, this is simplified for example sake. it's not really like this there
is a lot of async calls and callbacks etc. Now, if I check and mySocket is
not connected, or if i get an error back from .send, I shutdown that socket
and remove it from the hashtable. When processing one at a time, this works
fine.

My problem is that there is one instance where I have to loop through the
entire hash table of sockets and do a .Send. In that instance, if i have a
bad socket and want to remove it from the Hashtable...i get the problem i
originally described. So, databases, etc. don't fit my problem domain.

-Ken
"Cor Ligthert" wrote:
Ken,

I have the idea that you are not iterating through the keys of the
hasthtable but throught the values.

In my idea is that not where the hashtable is not made for, in that case by
instance the datatable does a much better job as collection because you have
much more methods to get the values from the objects in the datarow and
remove when needed those rows.

However maybe I see something wrong?

Cor

Nov 21 '05 #7
Well, I simplified my model for brevity. What I have is more complicated but
boils down to a hash table of open TCP sockets with the key being some
internal identifier. Normal processing is, given an identifier, I do
mySocket = myHashTable(identifier)
mySocket.send("blah")
again, this is simplified for example sake. it's not really like this there
is a lot of async calls and callbacks etc. Now, if I check and mySocket is
not connected, or if i get an error back from .send, I shutdown that socket
and remove it from the hashtable. When processing one at a time, this works
fine.

My problem is that there is one instance where I have to loop through the
entire hash table of sockets and do a .Send. In that instance, if i have a
bad socket and want to remove it from the Hashtable...i get the problem i
originally described. So, databases, etc. don't fit my problem domain.

-Ken

"Cor Ligthert" wrote:
Ken,

I have the idea that you are not iterating through the keys of the
hasthtable but throught the values.

In my idea is that not where the hashtable is not made for, in that case by
instance the datatable does a much better job as collection because you have
much more methods to get the values from the objects in the datarow and
remove when needed those rows.

However maybe I see something wrong?

Cor

Nov 21 '05 #8
You can try using the 'HashList':
http://www.codeproject.com/csharp/ha...arget=hashlist

hope that helps..
Imran.

"Ken Foster" <Ke*******@discussions.microsoft.com> wrote in message
news:02**********************************@microsof t.com...
I have a hashtable keyed by some name, holding an instance of an object. Most of the time I use the hashtable in the traditional sense, given a name, I
lookup the object, then I run a method on that object. Occaisionally however I need to run a method on every object in the hashtable. I've done both
For..Each and iEnumeratior loops. The messy part is that under certain
conditions, while iterating, a condition exists where I need to remove an
object from the hashtable. With ArrayLists I handle this with a reverse
iteration (from last to first) and do a .RemoveAt. Hashtables do not have
.RemoveAt. For..Each doesnt work because .Remove needs the key and I only
have the object, iEnumerator doesn't work because I get an error after the
first .Remove saying my enumerator is now invalid, so I can't continue that iteration.

I've thought about several solutions mostly inlvolving separate threads, but wanted to know if there was a cleaner way to handle this. Anyone come across this? It seems like a fairly standard problem, there must be some "pattern" solution.
-Ken

Nov 21 '05 #9
Interesting, and worth noteing for possible use in the future, but the
problem it solves (being able to iterate through a hashtable in FIFO order)
is not the problem I have, I don't care what order it's in. And at first
blush it looks like the .Remove during an enumeration will have the same
problems that a regular Hashtable has.

Thanks for that though.

"Imran Koradia" wrote:
You can try using the 'HashList':
http://www.codeproject.com/csharp/ha...arget=hashlist

hope that helps..
Imran.

"Ken Foster" <Ke*******@discussions.microsoft.com> wrote in message
news:02**********************************@microsof t.com...
I have a hashtable keyed by some name, holding an instance of an object.

Most
of the time I use the hashtable in the traditional sense, given a name, I
lookup the object, then I run a method on that object. Occaisionally

however
I need to run a method on every object in the hashtable. I've done both
For..Each and iEnumeratior loops. The messy part is that under certain
conditions, while iterating, a condition exists where I need to remove an
object from the hashtable. With ArrayLists I handle this with a reverse
iteration (from last to first) and do a .RemoveAt. Hashtables do not have
.RemoveAt. For..Each doesnt work because .Remove needs the key and I only
have the object, iEnumerator doesn't work because I get an error after the
first .Remove saying my enumerator is now invalid, so I can't continue

that
iteration.

I've thought about several solutions mostly inlvolving separate threads,

but
wanted to know if there was a cleaner way to handle this. Anyone come

across
this? It seems like a fairly standard problem, there must be some

"pattern"
solution.
-Ken


Nov 21 '05 #10
Ken,
If my routine normally wanted to remove a minority of the entries, I would
consider using a For Each on the HashTable, adding each entry to remove to
an ArrayList. Then when I finished the HashTable I would use a For Each on
the ArrayList removing each item from the HashTable.

If my normally wanted to remove a majority of the entries, I would consider
using a For Each on the HashTable, adding each entry to save to a new
HashTable. Then when I finished I would replace the old hash table with the
new hashtable. Alternatively I might Clone the HashTable, clear the original
& For Each on the Clone...

I have used variations of Jonas's idea also.

Hope this helps
Jay

"Ken Foster" <Ke*******@discussions.microsoft.com> wrote in message
news:02**********************************@microsof t.com...
I have a hashtable keyed by some name, holding an instance of an object.
Most
of the time I use the hashtable in the traditional sense, given a name, I
lookup the object, then I run a method on that object. Occaisionally
however
I need to run a method on every object in the hashtable. I've done both
For..Each and iEnumeratior loops. The messy part is that under certain
conditions, while iterating, a condition exists where I need to remove an
object from the hashtable. With ArrayLists I handle this with a reverse
iteration (from last to first) and do a .RemoveAt. Hashtables do not have
.RemoveAt. For..Each doesnt work because .Remove needs the key and I only
have the object, iEnumerator doesn't work because I get an error after the
first .Remove saying my enumerator is now invalid, so I can't continue
that
iteration.

I've thought about several solutions mostly inlvolving separate threads,
but
wanted to know if there was a cleaner way to handle this. Anyone come
across
this? It seems like a fairly standard problem, there must be some
"pattern"
solution.
-Ken

Nov 21 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

34 posts views Thread by Christopher Benson-Manica | last post: by
6 posts views Thread by Gustaf Liljegren | last post: by
5 posts views Thread by francois | last post: by
3 posts views Thread by Fred | last post: by
4 posts views Thread by Dahab | last post: by
reply views Thread by Marylou17 | last post: by
1 post views Thread by Marylou17 | last post: by
1 post views Thread by Marylou17 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.