[Closed] Associative arrays in max
Hi all,
As max doesn’t have a construct for associative arrays, I set about writing a basic Dictionary struct, similar to VB and such like:
names = #("five", "four", "three", "two", "one")
values = #(5,4,3,2,1)
arr = Dictionary()
for i = 1 to 5 do arr.addItem names[i] values[i]
I can get items by name, index, update items, etc., and do things like…
…printing:
arr.print() -- unsorted
five: 5
four: 4
three: 3
two: 2
one: 1
…sorting:
arr.sort() -- by name
five: 5
four: 4
one: 1
three: 3
two: 2
arr.sort field:#value -- by value
one: 1
two: 2
three: 3
four: 4
five: 5
However, it then occurred to me that I might be able to just use a dotNet class for this, and save having to load in a script each time.
I don’t really know anything about dotNet though. Is this possible?
How would I go about accessing and creating a Dictionary / Collection, then add items to it, sort it, etc?
Thanks for the input,
Dave
Hi Dave,
AFAIK, there’s no way to use .net for this, at least not with maxscript. There is System.Collections.Hashtable which allows you to store key/value pairs, but as it is a hashtable, it’s not sortable. Same goes for System.Collections.Specialized.StringDictionary, which also uses a hash table to store its data.
Martijn
Hi Martijn,
Thanks fpr that. Sorting isn’t a massive prioroty, it’s just a “nice to have”, and will probably come in useful at some point.
I did some tinkering with HashTable earlier, after a bit of Googling, but it didn’t seem to reveal any useful-looking methods in max.
Do you know how would I go about using the HashTable dotNet class?
Cheers,
Dave
Well, the annoying thing about using this class in mxs, is that it only accepts dotNetObjects as keys/values. I suppose you could work around this by writing a wrapper function which automatically converts the value. Not sure if this is worth the trouble though.
The other class I mentioned does accept mxs values, but only strings. So that’s probably not an option.
Anyway, here’s a quick example of creating a hash table:
(
HashTbl = dotNetObject "System.Collections.Hashtable"
HashTbl.Add (dotNetObject "System.Int32" 1) (dotNetObject "System.String" "First Entry")
HashTbl.Add (dotNetObject "System.String" "Two") (dotNetObject "System.String" "Second Entry")
clearListener()
format "1 : %
" HashTbl.Item[dotNetObject "System.Int32" 1]
format "Two : %
" HashTbl.Item[dotNetObject "System.String" "Two"]
format "
Properties :
"
showProperties HashTbl
format "----------------------------------------------
"
format "Methods :
"
showMethods HashTbl
)
Cheers,
Martijn
Not sure if it will help what you are trying to do but what about an array of structs?
dataAr=#()
struct data (name,data)
for i = 1 to 10 do
(
d=data()
d.name=i as string
d.data=i*10
append dataAr d
)
Thanks fellas,
Eugh… that .net stuff looks super-messy (code-wise), so I think I’ll avoid the hassle.
I could happily use a 2-part struct to store items, but I’m going with a couple of internal arrays at the mo. I guess it’s slightly cleaner (definition-wise), and still provides the functionality I need.
I’ll post when done and you can pick it apart anyway.
Cheers for the input,
Dave
Whadya know, I went with an array of structs in the end.
Even though it’s not as clean, it’s definitely more intuitive to think of name value pairs than an array of names and an array of values. Thanks Paul.
“List” makes easy to store and retrieve arbitrary values.
Properties
[ul]
[li]<array> items <name> <value> – the key/value pairs.[/li][list]
[li]Names can be a #name, “string”, or even an index[/li][li]Values can be any MaxWrapper value (i.e. anything)[/li][/ul]
[/list] Setters
[ul]
[li]<ListItem> addItem <name> <value> – adds an item to the List, and if it already exists[/li][li]<ListItem> setItem <name> <value> – synonym for the above[/li][/ul] Getters
[ul]
[li]<value> getValue <name> – returns the value of the named item[/li][li]<index> getIndex <name> – returns the index of the named item[/li][li]<name> getName <value> – returns the name of the first item that matches the supplied value[/li][li]<ListItem> getItem <name> – returns the List item corresponding to the supplied name (typically, you wouldn’t use this, as you know the name component already, it’s just included for completeness)[/li][li]<array> getItems() – returns all items as an array of ListItem structs[/li][li]<array> getNames() – returns all names as an array[/li][li]<array> getValues() – returns all values as an array[/li][/ul] Clear or delete
[ul]
[li]<array> clear() – clears the lit of all items, and returns the empty ListItems array[/li][li]<boolean> deleteItem <name> – deletes the named item from the list, and returns it[/li][li]<boolean> deleteIndex <index> – deletes the item at the index, and returns it[/li][/ul] Utilities
[ul]
[li]<array> sort field:<name> order:<name> func:<function> – sorts the list in a variety of ways, even supply a comparison function (see the max help on qsort)[/li][li]<string> print() – prints the List items to the Listener[/li][/ul]
Demos & download here: http://www.keyframesandcode.com/code/development/maxscript/list-struct/
Cheers,
Dave