Hash tables

Hi folks,

It's been a while, but I'm getting back into IPP. Some of the stuff I'm working on was really limited by the lack of hash tables (aka collections, associative arrays, etc.) so I decided to create them. If you think you could benefit from hash tables, this script should help a fair bit.
# To declare a hash... don't do anything.
#
# However, to *use* a hash, you must first ensure that the program knows what hash you're referring to.
# If you're only working with one hash, it's easy.  Near the start of your ipt file, do this:
#
# set: currHash =myHash
#
# If you're going to be working with more than one hash, then whenever you want to change the current 
# hash do this: {currHash=='myHash'} before you use the hash functions.  The single quotes are quite 
# important.  Also, of course, "myHash" can be pretty much whatever you want.
#
# THE FUNCTIONS
#
# To add a key-value pair to a hash (or change an existing key's value):
# [@HashSet with key, value]
#
# To get a value from a hash:
# [@HashGet with key]
#
# To remove a key-value pair from a hash:
# [@HashRemove with key]
#
# To get a count of hash keys:
# [@HashCount&;#93;
#
# To loop through the keys of the hash:
#   (in this example, using the keys to get the values, and comma-separating the values)
# [@&;#91;@HashCount&;#93; HashKeys >> each HashGet >> implode]
#

table: HashSet
{{currHash}{$1}=='{$2}'}&
[when][{{currHash}KeyList} >> length]=0[do]{{currHash}KeyList=='|'}[end]&
[when][{{currHash}KeyList} >> at |{$1}|]=0[do]{{currHash}KeyList=='{{currHash}KeyList}{$1}|'}[end]

table: HashGet
{{currHash}{$1}}

table: HashKeys
[when][{tempHashKeyList} >> length]=0[do]{tempHashKeyList=='[{{currHash}KeyList} >> substr 2 0]'}[end]&
{pos==[{tempHashKeyList} >> at |]}&
{returnKey=='[{tempHashKeyList} >> substr 1 {{pos}-1}]'}&
{tempHashKeyList=='[{tempHashKeyList} >> substr {{pos}+1} 0]'}&
{returnKey}

table: HashCount
[when]{IveBeenHereBefore}<>yes[do]{HashCountCounter==0}{IveBeenHereBefore=='yes'}{tempHashKeyList=='[{{currHash}KeyList} >> substr 2 0]'}[end]&
{pos==[{tempHashKeyList} >> at |]}&
[when]{pos}=0[do]{HashCountCounter}{IveBeenHereBefore=='no'}[else]{HashCountCounter=={HashCountCounter}+1}{tempHashKeyList=='[{tempHashKeyList} >> substr {{pos}+1} 0]'}[@HashCount&;#93;[end]&
{tempHashKeyList==''}


table: HashRemove
{pos==[{{currHash}KeyList} >> at |{$1}|]}&
[when]{pos}>0[do]&
{halfHash1=='[{{currHash}KeyList} >> substr 1 {pos}]'}&
{halfHash2=='[{{currHash}KeyList} >> substr {{pos}+1} 0]'}&
{pos==[{halfHash2} >> at |]}&
{{currHash}KeyList=='{halfHash1}[{halfHash2} >> substr {{pos}+1} 0]'}&
{{currHash}{$1}==''}&
[end]

This script (which expects Hashes.ipt to exist in common/nbos/) shows hashes in action:
use: common/nbos/Hashes.ipt

table: test
{currHash=='myhash'}&
[@HashSet with dog, house][@HashSet with chicken, coop][@HashSet with animal, farm]&
;
Keys of myHash:\n&
[@&;#91;@HashCount&;#93; HashKeys >> implode]\n\n&
Values of myHash:\n&
[@&;#91;@HashCount&;#93; HashKeys >> each HashGet >> implode]\n\n&
;
[@HashRemove with chicken]&
;
Keys of myHash after removing "chicken":\n&
[@&;#91;@HashCount&;#93; HashKeys >> implode]\n\n&
;
[@HashRemove with animal]&
;
Keys of myHash after removing "animal":\n&
[@&;#91;@HashCount&;#93; HashKeys >> implode]\n\n&
;
[@HashSet with pig, pen]&
;
Keys of myHash after adding "pig":\n&
[@&;#91;@HashCount&;#93; HashKeys >> implode]\n\n&
Values of myHash:\n&
[@&;#91;@HashCount&;#93; HashKeys >> each HashGet >> implode]\n\n&
Count of myHash:\n&
[@HashCount&;#93;\n\n&
;
{currHash=='otherHash'}&
[@HashSet with pickle, relish][@HashSet with tomato, ketchup][@HashSet with peanut, peanut butter][@HashSet with counter, 1]&
;
Keys of otherHash:\n&
[@&;#91;@HashCount&;#93; HashKeys >> implode]\n\n&
Values of otherHash:\n&
[@&;#91;@HashCount&;#93; HashKeys >> each HashGet >> implode]\n\n&
;
[@HashSet with counter2, {[@HashGet with counter2]+1}]&
;
Keys of otherHash after adding (by incrementing an undeclared key) counter2:\n&
[@&;#91;@HashCount&;#93; HashKeys >> implode]\n\n&
Values of otherHash:\n&
[@&;#91;@HashCount&;#93; HashKeys >> each HashGet >> implode]\n\n&
Value of counter in otherHash:\n&
[@HashGet with counter]\n\n&
;
[@HashSet with counter, {[@HashGet with counter]+1}]&
[@HashSet with counter, {[@HashGet with counter]+1}]&
;
Value of counter in otherHash after incrementing twice:\n&
[@HashGet with counter]\n\n&
;
[@HashRemove with chicken]&
;
;  below, removing "tomato" does nothing, because "tomato" doesn't exist in otherHash.
[@HashRemove with tomato]&
;
{currHash=='myHash'}[@HashSet with counter, kitchen]&
;
Value new key "counter" in myHash:\n&
[@HashGet with counter]\n\n&
Value old key "counter" in otherHash:\n&
{currHash=='otherHash'}[@HashGet with counter]\n\n&
Number of keys in otherHash:\n&
{currHash=='otherHash'}[@HashCount&;#93;\n\n


Hope someone finds this useful!

Comments

  • Hi, just dl & installed the program but I don't have a Hashes.ipt in common/nbos/. I thought perhaps it was the first code block in this post and created a Hashes.ipt with it but that didn't work either.
    Where do I get the correct Hashes.ipt for them to work?
    Thanks!

  • I assume it's the first block as well. I've not messed with it, so I'll put it in and see if it works for me. Are you getting any specific error when trying to use it?

  • So, I think the problem is that the code brackets are showing the tags as their character string. Instead of '[' I'm seeing '['

    Set this up on my end, fixed the tags and used the gem example from the other post at http://forum.nbos.com/discussion/1116/recursive-roll-subtracting-from-randomly-generated-total#latest

    Wanted to attach the file, but wasn't allowed to, so I posted it over at NBOS IPP3 download page - http://www.nbos.com/nox/index.php?pcatid=49

    I then ran the following code from the gem example, and it worked like a charm.

    use: common/nbos/Hashes.ipt

    Set: currHash =myHash

    table: start
    [@{2d6} Gems >> each AddToHash] &
    [@[@HashCount] HashKeys >> each ShowResults >> implode]

    table: ShowResults
    [@HashGet with {$1}] {$1}

    table: AddToHash
    [@HashSet with {$1}, {[@HashGet with {$1}]+1}]

    table: Gems
    diamonds
    rubies
    opals
    emeralds
    sapphires

  • This is pretty fantastic. Still working on it though. Any chance someone could post this in the 3.0 official documentation, with comments and examples? Could be very helpful for those of us who are not programmers.

  • Well, it is user created so I don't think it will get 'official' support or documentation. The information in the OP has documentation and examples. If you're stuck on a certain part I'd be happy to try and help.

  • Thanks Kathorus,
    Works like a charm now and I can dupe it for some other generators as well.

Leave a Comment