Since many people were impressed with my named parameters article, I decided to write up another post about the dictionary functions. Actually in all fairness I think three people actually liked it. Vincenzo Menanno, Chris Wack and Sam Barnum this post's for you!
Note: This article was revised November 23, 2007. I added the handy
DictReplacefunction. -Geoff
First I must warn you, I have left the names of the custom functions the same as the functions we use internally. This means they may seem a little obtuse so feel free to change them. I'm also not getting to in-depth into how they actually work because it could take an extra 5 pages or so (yea I know Geoff... I'm lazy... deal with it). I'm sure most of you will get them pretty quickly despite my inept explanations. Oh yea, I also suggest going back and reading the named parameters post before getting into this post otherwise it probably won't make much sense.
Enjoy...
Note: For the duration of this article I will refer to the custom function
PassParameter( name ; value )in my previous post as #( ). This saves me 12 key strokes and won't confuse me because that's what I call it internally.
Using a Dictionary in the Script Result
I actually posted this in the comments of the Named Parameters post. The idea here is that you can not only use the named parameter idea in your script parameters but in your script results as well. So just place your dictionary values in the script result dialog of the Exit Script script step and you've go yourself named script results. I like to create a little shortcut to access them like so:
Name: #R ( name )
Definition:
DictGet( Get(ScriptResult) ; name )
Checking for a Name in the Dictionary
There's also a point where you may want to check if your dictionary contains a certain value. You could do this by simple using your DictGet() custom function on your Dict. By design, a call to the DictGet() will return empty if the name you are looking for isn't there. That's when I made DictContains?
Name: DictContains?( dict, name )
Definition
Let(
pattern = "<:" & name & ":=";
Position(dict; pattern; 1; 1) > 0
)
All this is doing is checking the dictionary structure for the name of the value you are looking for and returning true if it finds the value and false if it doesn't.
Note: This will not find any nested dictionary values. So if you were to store a dictionary within a dictionary ie. #( "Account" ; #( "Name" ; "Jesse" ) & #( "Job" ; "Writing confusing custom functions" ) ) you wouldn't be able to use the
DictContains?custom function to see ifJobis in the dictionary because it is inside the account dictionary.
Removing an Entry from a Dictionary
You never know when, but there will be a point where you think... "Man, I wish I could remove a value from my dictionary." Well, maybe you won't... but I wrote this thing anyway. If you happen to bump into this situation, you can use the nifty function below. DictRemove() simply removes the dictionary name/value pair specified from the dictionary passed in.
Name: DictRemove( dict, name )
Definition:
Let(
[
pattern = "<:" & name & ":=";
entry_start = Position( dict ; pattern ; 1 ; 1);
entry_end = Position( dict ; ":>" ; entry_start + 1; 1);
dict_beginning = If( entry_start > 0 ; Left ( dict ; entry_start - 1 ) );
rest_of_dict = Middle( dict ; entry_end + 2 ; 999999 );
new_dict = dict_beginning & rest_of_dict
];
If( entry_start > 0 ; new_dict ; dict )
)
Replacing an Entry in a Dictionary
This function is primarily for convenience. It combines DictRemove with a new entry to effectively replace a value in the dictionary in one shot:
Name: DictReplace ( dict, name, value )
DictRemove(dict, name) & #(name, value)
Returning the Top Name in a Dictionary
This custom function was designed to return the name of the first name-value pair in the dictionary. Nothing too special, but I if used in conjunction with the DictRemove() function above, you can pop off the top value of the dictionary with ease.
Name: DictFirst( dict )
Definition:
Let(
[startValue = "<:";
endValue = ":=";
positionOfStartValue= Position( dict ; startValue ; 1 ; 1 );
endOfStartValue= If( positionOfStartValue > 0 ; positionOfStartValue + Length(startvalue); -1 );
beginningOfEndValue= Position( dict; endValue; endOfStartValue; 1 );
found = If( beginningOfEndValue > -1 and endOfStartValue > -1 ; True; False );
lengthFoundValue = beginningOfEndValue - endOfStartValue;
foundValue = Middle( dict; endOfStartValue ; lengthFoundValue )];
If( found ; foundValue ; "" )
)
Adding to a Dictionary
This custom function is ridiculously easy. It's really just a shortcut that looks a little more succinct then actually performing the action manually.
Name:DictAdd( dict; name; value )
Definition:
dict & #( name ; value )<br>
Dictionary To String
This is quite frankly my favorite custom function ever. Serioulsy, I have a ton of ridiculous functions that no one uses but me, but this is the creme de la creme. I'll get slightly more indepth about this function because it can be a little tricky to understand. Here is the signature of the function:
Name: DictToString
Parameters:
Dict: A dictionary of your choosing
Format: format you would like to display the data in.
The real magic of this function comes from the Format parameter. This parameter will dictate how you want the data displayed. The function goes through each and every dictionary entry and will put it into whichever format you specific. To achieve this functionality a replace is performed on the Format. $name is replaced with the name of the dictionary entry and $value is replaced with the value of the dictionary entry. Here is the function:
Name: DictToString( Dict ; Format )
Definition:
Let(
[
firstName = DictFirst ( dict );
rawdata = DictGet(dict; firstName) ;
data = If( not IsEmpty( DictFirst( rawdata ) ) ; DictToString( rawdata ; Format ); rawdata );
rest = DictRemove( dict ; firstName )
];
If( not IsEmpty(firstName) ;
Substitute(
format;
["$name"; firstName ];
["$value"; data ]
)
&
If (
not IsEmpty(rest);
DictToString(rest; Format)
)
; dict )
)
Let's say your Format parameter is:
`"$name is $value"`
and your dictionary is
`<:Jesse:=nuts:>`
the output would be
`Jesse is Nuts`
You can now basically output your dictionaries in any format you so desire. Such as.... you guessed it.... XML.
Dictionary To XML
So once you understand the DictToString() custom function, the DictToXML() function is just a shortcut that I wrote so I don't have to write the funky format over and over. Here is is:
Name: DictToXML ( dict )
Definition:
DictToString ( dict , "<$name>$value<$name>" )
Let's say you setup your dictionary like so #( "account" ; #( "name" ; "Jesse" ) & #( "birthday" ; "Yesterday" ) ). You'll notice that I have put a pair of dictionaries within another dictionary named account. The DictToXML function (really the DictToString() function does the bulk of the work but you get the point) will actually iterate through the outside and inside dictionary and output the following:
<account>
<name>Jesse</name>
<birthday>Yesterday</birthday>
</account>
This can be very useful for creating tidbits of xml to post to web actions. Sweet Huh?