• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[General] Question About Hashtables

Status
Not open for further replies.
The action "Clear Parent Hashtable" is sadly wrongly named, it destroys the Hashtable, making it unuseable, like you said.

Yes, things that leak can also leak when using a Hashtable. Reference is only reference does not matter, if the referencer is a Hashtable cell, an array or a variable. But I have such a feeling i should give you a link explaining what a leak is: Checkout this post from IcemanBo: Memory Leaks
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
read the hashtable cell and use the destroy/Remove function suited for the gained object onto it. Then object refered in the hastable cell is destroyed.

RemoveLocation(LoadLocationHandle(...))
Oh, thank you
Edit, I have to null the values of the Hashtable?, because I think that values will be there forever if its not and I think this apply even with non-reference values.
 
Last edited:
if you reuse the same cell in near future again than you don't need to null it. But if you do not then it is a good idea to clear the cell/child table.
In written code you can use natives to clear a specific cell. In GUI you can only rewrite a specific cell or clear a whole child table.
JASS:
native  RemoveSavedInteger                  takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedReal                     takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedBoolean                  takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedString                   takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedHandle                   takes hashtable table, integer parentKey, integer childKey returns nothing
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
if you reuse the same cell in near future again than you don't need to null it. But if you do not then it is a good idea to clear the cell/child table.
In written code you can use natives to clear a specific cell. In GUI you can only rewrite a specific cell or clear a whole child table.
JASS:
native  RemoveSavedInteger                  takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedReal                     takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedBoolean                  takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedString                   takes hashtable table, integer parentKey, integer childKey returns nothing
native  RemoveSavedHandle                   takes hashtable table, integer parentKey, integer childKey returns nothing
Oh I see
 
In case you use GUI. In GUI the mentioned order is overthrown, compared to the natives I posted.
  • Hashtabelle - Save 0.00 as child of parent in (Last created hashtable)
One can imagine the whole Hashtable like that:
There is a shelf (Hashtable), in that shelf are many books each parent Key leads to one book. Each book has pages, a page is reached over the child Key.

These Remove/Save actions write onto one page.
 
Level 24
Joined
Jun 26, 2020
Messages
1,852
In case you use GUI. In GUI the mentioned order is overthrown, compared to the natives I posted.
  • Hashtabelle - Save 0.00 as child of parent in (Last created hashtable)
One can imagine the whole Hashtable like that:
There is a shelf (Hashtable), in that shelf are many books each parent Key leads to one book. Each book has pages, a page is reached over the child Key.

These Remove/Save actions write onto one page.
And I think the first integer is the parent and the second, the child, now I have to change the order of the keys in my hashtables.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,542
Just to help anyone else confused by Hashtables, here's how I look at it.

Parent = Category
Children = Data being stored under that Category

The Children are basically a normal 1-dimensional Array:

Child[1] = some data
Child[2] = some data
Child[3] = some data

But they're linked to a Parent:

Parent[1]Child[1] = some data
Parent[1]Child[2] = some data
Parent[1]Child[3] = some data

^That's basically the same thing as a 2-dimensional Array:

Hashtable[1][1] = some data
Hashtable[1][2] = some data
Hashtable[1][3] = some data

If you've ever been creating Array variables for specific players like this:
Player1Hero[1] = Some Unit
Player1Hero[2] = Some Unit
Player1Hero[3] = Some Unit

Player2Hero[1] = Some Unit
Player2Hero[2] = Some Unit
Player2Hero[3] = Some Unit

Stop! What you really want to use is a Hashtable.

Here's what you should NOT be doing:
  • Bad Example
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering player) Equal to Player 1 (Red)
        • Then - Actions
          • Unit - Kill Player1Hero[1]
          • Unit - Kill Player1Hero[2]
          • Unit - Kill Player1Hero[3]
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering player) Equal to Player 2 (Blue)
            • Then - Actions
              • Unit - Kill Player2Hero[1]
              • Unit - Kill Player2Hero[2]
              • Unit - Kill Player2Hero[3]
            • Else - Actions
And here's the same thing using a Hashtable.
There's no need for checking which Player it is, we can simply load our saved Data (Children) using the Player's Number as the Category (Parent):
  • Hashtable Example
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
    • Conditions
    • Actions
      • Set Variable PN = (Player number of (Triggering player))
      • Unit - Kill (Load 1 of PN in HeroHashtable)
      • Unit - Kill (Load 2 of PN in HeroHashtable)
      • Unit - Kill (Load 3 of PN in HeroHashtable)
And if you're wondering about how to actually save this stuff to a Hashtable, here's an example of setting it all up:
  • Save to Hash Example
    • Events
      • Time - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • -------- First make sure to actually create the Hashtable and keep track of it using a Hashtable variable: --------
      • Hashtable - Create a hashtable
      • Set Variable HeroHashtable = (Last created hashtable)
      • -------- --------
      • -------- Next, let's create and store Player 1's Heroes to the Hashtable: --------
      • Set Variable PN = 1
      • -------- --------
      • Unit - Create 1 Paladin for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 1 of PN in HeroHashtable.
      • Unit - Create 1 Archmage for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 2 of PN in HeroHashtable.
      • Unit - Create 1 Mountain King for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 3 of PN in HeroHashtable.
      • -------- --------
      • -------- Next, let's create and store Player 2's Heroes to the Hashtable: --------
      • Set Variable PN = 2
      • -------- --------
      • Unit - Create 1 Paladin for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 1 of PN in HeroHashtable.
      • Unit - Create 1 Archmage for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 2 of PN in HeroHashtable.
      • Unit - Create 1 Mountain King for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 3 of PN in HeroHashtable.
I'm using that PN integer as a shortcut to remember the Player's Number. Techniques like that are not necessary and should only be used if you know what you're doing.

Also, note that Hashtables have a limit. I believe you can only sustain 255 Hashtables at a time. That being said, if you master the Hashtable you could potentially use 1 Hashtable for EVERYTHING, or at the very least for more than 1 thing.

Additionally, Hashtables have the ability to save Data (Children) to just about anything. Meaning your Category (Parent) doesn't have to be an Integer, it can be a Unit for example. What does that mean? It means that you can save Data directly to a specific Unit, which is extremely useful for making MUI spell effects and custom stats like Ability Power.

An example of this, whenever a Hero gains a Level their Ability Power stat is increased by 5:
  • Ability Power
    • Events
      • Unit - A unit Gains a level
    • Conditions
    • Actions
      • Set Variable AbilityPower = (Load 1 of (Key (Triggering unit)) from StatHashtable.)
      • Hashtable - Save (AbilityPower + 5) as 1 of (Key (Triggering unit)) in StatHashtable.
AbilityPower is an Integer variable that I use to contain the loaded Data from the Hashtable. It isn't necessary but helps keep things easy to read.

Here's an example without it:
  • Ability Power
    • Events
      • Unit - A unit Gains a level
    • Conditions
    • Actions
      • Hashtable - Save ((Load 1 of (Key (Triggering unit)) from StatHashtable) + 5) as 1 of (Key (Triggering unit)) in StatHashtable.
 
Last edited:
Level 24
Joined
Jun 26, 2020
Messages
1,852
Just to help anyone else confused by Hashtables, here's how I look at it.

Parent = Category
Children = Data being stored under that Category

The Children are basically a normal 1-dimensional Array:

Child[1] = some data
Child[2] = some data
Child[3] = some data

But they're linked to a Parent:

Parent[1]Child[1] = some data
Parent[1]Child[2] = some data
Parent[1]Child[3] = some data

^That's basically the same thing as a 2-dimensional Array:

Hashtable[1][1] = some data
Hashtable[1][2] = some data
Hashtable[1][3] = some data

If you've ever been creating Array variables for specific players like this:
Player1Hero[1] = Some Unit
Player1Hero[2] = Some Unit
Player1Hero[3] = Some Unit

Player2Hero[1] = Some Unit
Player2Hero[2] = Some Unit
Player2Hero[3] = Some Unit

Stop! What you really want to use is a Hashtable.

Here's what you should NOT be doing:
  • Bad Example
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Triggering player) Equal to Player 1 (Red)
        • Then - Actions
          • Unit - Kill Player1Hero[1]
          • Unit - Kill Player1Hero[2]
          • Unit - Kill Player1Hero[3]
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Triggering player) Equal to Player 2 (Blue)
            • Then - Actions
              • Unit - Kill Player2Hero[1]
              • Unit - Kill Player2Hero[2]
              • Unit - Kill Player2Hero[3]
            • Else - Actions
And here's the same thing using a Hashtable.
There's no need for checking which Player it is, we can simply load our saved Data (Children) using the Player's Number as the Category (Parent):
  • Hashtable Example
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 2 (Blue) leaves the game
      • Player - Player 3 (Teal) leaves the game
    • Conditions
    • Actions
      • Set Variable PN = (Player number of (Triggering player))
      • Unit - Kill (Load 1 of PN in HeroHashtable)
      • Unit - Kill (Load 2 of PN in HeroHashtable)
      • Unit - Kill (Load 3 of PN in HeroHashtable)
And if you're wondering about how to actually save this stuff to a Hashtable, here's an example of setting it all up:
  • Save to Hash Example
    • Events
      • Time - Elapsed game time is 1.00 seconds
    • Conditions
    • Actions
      • -------- First make sure to actually create the Hashtable and keep track of it using a Hashtable variable: --------
      • Hashtable - Create a hashtable
      • Set Variable HeroHashtable = (Last created hashtable)
      • -------- --------
      • -------- Next, let's create and store Player 1's Heroes to the Hashtable: --------
      • Set Variable PN = 1
      • -------- --------
      • Unit - Create 1 Paladin for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 1 of PN in HeroHashtable.
      • Unit - Create 1 Archmage for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 2 of PN in HeroHashtable.
      • Unit - Create 1 Mountain King for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 3 of PN in HeroHashtable.
      • -------- --------
      • -------- Next, let's create and store Player 2's Heroes to the Hashtable: --------
      • Set Variable PN = 2
      • -------- --------
      • Unit - Create 1 Paladin for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 1 of PN in HeroHashtable.
      • Unit - Create 1 Archmage for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 2 of PN in HeroHashtable.
      • Unit - Create 1 Mountain King for Player 2 (Blue) at (Center of (Playable map area)) facing Default building facing degrees
      • Hashtable - Save Handle Of (Last created unit) as 3 of PN in HeroHashtable.
Ok, thanks for the explanation
 
I have another question, how many children hashtables can have a category or parent hashtables?
Preferably less than 100 000, but definitvly less than 2 500 000 if you care about performance. Technically it should handle 2^32 for a child-table. I rarely use more than 30-40 values though and it was a long time since I tested anything...
 
Status
Not open for further replies.
Top