PDA

View Full Version : Associative arrays in max


davestewart
06-06-2008, 12:17 AM
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

magicm
06-06-2008, 01:04 AM
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

davestewart
06-06-2008, 01:13 AM
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

magicm
06-06-2008, 01:22 AM
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 : %\n" HashTbl.Item[dotNetObject "System.Int32" 1]
format "Two : %\n" HashTbl.Item[dotNetObject "System.String" "Two"]

format "\nProperties :\n"
showProperties HashTbl
format "----------------------------------------------\n\n"
format "Methods :\n"
showMethods HashTbl

)
Cheers,
Martijn

PEN
06-06-2008, 01:31 AM
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
)

davestewart
06-06-2008, 01:47 AM
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

davestewart
06-06-2008, 08:17 PM
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



<array> items <name> <value> - the key/value pairs.

Names can be a #name, "string", or even an index
Values can be any MaxWrapper value (i.e. anything)

Setters



<ListItem> addItem <name> <value> - adds an item to the List, and if it already exists
<ListItem> setItem <name> <value> - synonym for the above
Getters



<value> getValue <name> - returns the value of the named item
<index> getIndex <name> - returns the index of the named item
<name> getName <value> - returns the name of the first item that matches the supplied value
<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)
<array> getItems() - returns all items as an array of ListItem structs
<array> getNames() - returns all names as an array
<array> getValues() - returns all values as an array
Clear or delete



<array> clear() - clears the lit of all items, and returns the empty ListItems array
<boolean> deleteItem <name> - deletes the named item from the list, and returns it
<boolean> deleteIndex <index> - deletes the item at the index, and returns it
Utilities



<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)
<string> print() - prints the List items to the Listener

Demos & download here: http://www.keyframesandcode.com/code/development/maxscript/list-struct/

Cheers,
Dave

CGTalk Moderation
06-06-2008, 08:17 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.