1 / 1
OpenSCAD Library for Hash data structure — zdjęcie 1

OpenSCAD Library for Hash data structure

Zamów wydruk tego modelu

Obliczymy ostateczną cenę na podstawie wybranego pliku. Sprawdzisz ją i zaakceptujesz przed płatnością.

Zapisane na tym urządzeniu.

OpenSCAD Library for Hash data structure (associative array)

Ocena
0 / 5
Polubienia
6
Pobrania
56
Wydruki
0
Wyświetlenia
439
Oceny
0

Aktualizacja u źródła:

Informacje o modelu

Źródło
Printables
Kategoria
Other Ideas
Licencja
Creative Commons — Attribution

For some complex OpenSCAD projects I wanted to have to ability to put many different settings for a module into one parameter as a hash / associative array. This would be useful when I have a large number of settings and module which call sub-modules which call sub-sub-modules.

Putting these settings into module parameters would be unwieldy, especially if I have to add a settings later. Putting these settings into global parameters prevents me from using the module with several different settings at the same time.

OpenSCAD does not natively support hashes / associative array (as of mid 2022). But it does have a search() function that can (among other things) locate a string in an array.

So I build this library that encapsulates the creation, modification and use of hashes.
This library can be used by including the following line:

use <af-hash.scad>

 

The basic use case is where I have a module that can receive any number of settings in one parameter, and I can call this module with different settings. Optionally the module calls a sub-module which also uses these settings.

Example:

use <af-hash.scad>

settings1 = hash_create([ "size", [10,20,30], "wall-thickness", 2, "hole-diameter", 5 ]); settings2 = hash_create([ "size", [20,30,60], "wall-thickness", 3, "hole-diameter", 8 ]);

translate([-30,0,0]) my_module(settings1); translate([30,0,0]) my_module(settings2);

module my_module(settings) { s = hash_get(settings, "size"); w = hash_get(settings, "wall-thickness"); [...] my_submodule(settings); [...] }

module my_submodule(settings) { w = hash_get(settings, "wall-thickness"); d = hash_get(settings, "hole-diameter"); [...] }

 

The functions in this library are (the most important function are in bold):

  • hash_create(array) - takes an array in the form [ key1, value1, key2, value2, … ] and converts it into a proper hash
  • hash_get(hash, key, [default_value = undef]) - searches in the hash for the given key and returns the associated value, returns the default value if the key was not found or if the assosiated value is undef
  • hash_get2(hash, key) - searches in the hash for the given key and returns the associated value and a flag that says if the key was found
  • hash_contains_key(hash, key) - tests if the hash contains the key
  • hash_set - returns a modified hash
    • hash_set(hash, key, value) - returns a hash where the key-value pair is added or, if the key already existed, the value is overridden
    • hash_set(hash, array) - same as above, but takes multiple key-value pair in the same format as hash_create
    • hash_set(hash1, hash2) - returns a hash were the entries of both input hashes are merged, values of hash2 override values with the same key from hash1
  • hash_empty() - creates an empty hash
  • hash_keys(hash) - returns a list of all keys in the hash
  • module hash_print(hash, [long_format = false]) - prints the hash to the console

Update 2022-07-30:

Added the following function:

  • hash_prune(hash) - creates a new hash with only the currently valid entries from parameter hash, overridden values are omitted

Some technical details:

Hashes are internally stored as a vector of vectors of key and value:

hash = [
	[ <key1>, <value1> ],
	[ <key2>, <value2> ],
	[ <key3>, <value3> ],
	etc.
];

Hash keys are automatically converted to strings both during creation of the hash and during access of the hash data.

Hash values can be any kind of data, including undef, number, vector, string or a hash.

As hash_print will show you, hash_set does not actually modify the old hash. Instead it puts the new values at the start of the newly generated hash: 

hash1 = [
	[ "abc", 1 ],
	[ "def", 2 ]
];
hash2 = [
	[ "def", 3 ],
	[ "ghi", 4 ]
];
hash3 = hash_set(hash1, hash2);
==> hash3 = [
	[ "def", 3 ],
	[ "ghi", 4 ],
	[ "abc", 1 ],
	[ "def", 2 ]
];

hash_get("def") will find the new value (3) first and return it instead of the old value (2).

A hash value can be “deleted” by overriding it with the value undef. The key still counts as contained in the hash, but hash_get will return the default value (which is also undef if not specified).

hash_create allows key-value pairs in sub-arrays, sub-sub-arrays etc., it will flatten the data into the above described hash structure:

hash = hash_create([ "ab",1, "cd",2, [ "ef",3, [ "gh",4 ] ], "ij",5 ]);
==> hash = [
	[ "ab", 1 ],
	[ "cd", 2 ],
	[ "ef", 3 ],
	[ "gh", 4 ],
	[ "ij", 5 ]
];

The value overriding mechanism can create quite big hashes. The output of hash_print will then be difficult to read. By using hash_prune the hash will be smaller because all overridden values are removed:

hash1 = hash_create([ "a",1, "b",2, "a",3, "c",4, "a",5 ]);
==> hash1 = [
	[ "a", 1 ],
	[ "b", 2 ],
	[ "a", 3 ],
	[ "c", 4 ],
	[ "a", 5 ]
];
hash2 = hash_prune(hash1);
==> hash2 = [
	[ "a", 1 ],
	[ "b", 2 ],
	[ "c", 4 ]
];

Tagi