How to remove TMap key by value instead?

BlitzMax Forums/BlitzMax Programming/How to remove TMap key by value instead?

Danny(Posted 2011) [#1]
I have an object stored as a value inside a TMap - and I wish to remove that object/entry from the TMap, but how do I do that?

I would need something like a TMap.RemoveByValue(value:object) in stead of the TMap.Remove(key:object)..

Thanks,
D.

Last edited 2011


Danny(Posted 2011) [#2]
The following function seems to work - but ONLY if the value exists!

I might have stumbled on a bug in Map.bmx's TNODE.NextNode() - when it goes beyond the end of the Map, it seems to get stuck in an infinite loop?!

In the example case below, if the value does not exists TNODE.NextNode() will never return scope to my function..




Last edited 2011


ima747(Posted 2011) [#3]
You could iterate the keys and check each one for the value... once you have the key then a normal remove and you're done... probably a way to optomize that by going at the map directly but it is friendly with the accepted functions etc. unless your map is quite big I don't think it would take all that long, and if performance is really an issue perhaps some other form of storage would be better suited?


Czar Flavius(Posted 2011) [#4]
You could have two maps and store the value and key swapped in the other map.

You could store the value's key as a field of that value. (My prefered solution)

Perhaps reconsider your design, why do you need to search by value and not key?

If you want to iterate through a map only once, you can use For Local value:MyType = EachIn map.Values()

Last edited 2011


Danny(Posted 2011) [#5]
Thanks.

For a script-like system I use a TMAP to look up a 'variable name' in the form of a string (eg. "CAMERA") to get a live object or handle that goes with it. This is what TMap does, so that works perfectly fine.

But when I want to purge any of those live objects from memory, I thus also need to go through the TMap and remove all references to that live object for it to be collected as garbage. At that time though, I only know the 'value' (the live object) and not the 'key' (the key/string name is custom).

Yes I considered an identical TMap and swap the values for the keys :) But my religion won't allow me to store the same information twice for this reason :)

So yeah, I guess you're both right in that I just need to use a TList or such and create my own look up table - which is a bit silly cause TMap already does 99% of what I need, but I can't figure out how it works internally to 'finish it' myself ;)

Cheers,
D.

Last edited 2011


Fry Crayola(Posted 2011) [#6]
Czar's solution of storing the key as a field of the value, so when it's added to the TMap you also update that field with the relevant key, is quite simple and relatively elegant. Is there any reason why you aren't able to do this?

Is the value being stored in multiple maps, which would then require multiple fields and edge into headache territory?

And if it's your religion, maybe it's time to convert. ;)


Czar Flavius(Posted 2011) [#7]
Storing information twice redunantly isn't a good thing, but if you do need it stored in two places, then it isn't redundant!

I don't know how your program state works, but is there any way you can have multiple maps for different state units of your program? Then when a particular state unit is over, you can clear everything in its map.

Or you can have lists of object keys of the same state unit and when that unit is over, go through the list and look up those objects and remove them. That will be just as fast as storing the keys with the object but will seperate out the two different concerns.

It sounds like you are making a kind of programming language. A common way to store and destroy variables in a programming language is by using a stack. Researching how the stack works in a language such as C/C++ may give you some new ideas for your own language.


Danny(Posted 2011) [#8]
I'm indeed working on node-based visual language where each node can have a private script running (and have its own private states and variables). The stack based approach seems the way to go for me.

Thanks for the brainstorm guys!

D.


Czar Flavius(Posted 2011) [#9]
That stack is good for variables which have a definate, constrained lifetime - eg local variables to functions, but it's not so good for large variables you want to persist out of a function. For example, if you want a function to make a new instance of an object and return it, where do you store that on the stack?

I don't know how deep you want to go with your language, but you could have a TMap "heap/freestore" for persistent variables and a stack for local variables. That means, when the time comes, you will need to manually order the heap variables to be deleted.

It's analogous to Blitz ints and floats (on the stack) and "New" type instances (on the heap), except Blitz has a garbage collector to delete them.


SculptureOfSoul(Posted 2011) [#10]
I think a hash table is a better data structure for your purposes.

I've got some hash table code here - http://www.blitzbasic.com/codearcs/codearcs.php?code=1907 - that you might like. It's extremely optimized and has the functionality you are looking for.

You can even store multiple objects with the same key and sort them by whatever type of priority you want to include by overloading an objects Compare() method. More to the point, you can remove all objects with a given key, a specific object with a specific key (useful when you have multiple objects w/ the same key but only want to remove one), or, when the key isn't known, remove by object (The functionality you are looking for. This is by necessity slower, as it must search the whole hash table, but there's really no other way around it).

If you think it might help at all, I can also dig up some code I started with that was all about making a scripting language of sorts that sits on top of BMax (but is written in Bmax, utilizing a hash table for each object to store its variables and functions, etc, to allow real time addition/removal of methods and variables). My original idea was to have objects that are completely modifiable in real time, and then have people program independent "behaviors" that could be attached to any object and would modify it however the behavior was programmed.

These behaviors could then be shared amongst programmers and be used in a plug-n-play fashion (eg: a 'follow object' behavior that has parameters for the object to follow, the speed to follow it, and perhaps a number of built in following algorithms that could be selected with a third parameter. This could be tacked onto any modifiable object and work on those dynamic variables it contains (adding any additional variables the behavior may need to the object and also perhaps the associated object [in this case, the target that is being followed]).

Anyhow, the framework that I started with is a bit rough in spots but it does at least allow dynamically adding functions and variables to objects, and I believe it also had the functionality to also add these functions/variables (or others) to parent/child objects of the object in question (not 100% sure as I haven't looked at the code in years).

Anyhow, hth. :)