Open ndrean opened 1 month ago
const std = @import("std");
fn count_occurrences(text: []const u8, allocator: std.mem.Allocator) !u32 {
var char_count = std.AutoHashMap(u8, usize).init(allocator);
defer char_count.deinit();
for (text) |char| {
// lookup if already existing or put 0
const count = char_count.get(char) orelse 0;
try char_count.put(char, count + 1);
}
// using the general iterator: "key" is a pointer", and the value is `key.key_ptr/*`
var it = char_count.iterator();
while (it.next()) |key| {
print("({c}, {?}), ", .{ key.key_ptr.*, char_count.get(key.key_ptr.*) });
}
// using the "key" iterator
var itk = char_count.keyIterator();
while (itk.next()) |key| {
print("{c}, {}", .{ key.*, char_count.get(key.*).? });
}
return char_count.count();
}
test "count" {
const char_count: u32 = try count_occurences("hello world to bob", std.testing.allocator);
std.testing.expect(char_count == 10);
}
(t, 1), ( , 3), (o, 4), (d, 1), (b, 2), (r, 1), (e, 1), (h, 1), (w, 1), (l, 3), [t, 1], [ , 3], [o, 4], [d, 1], [b, 2], [r, 1], [e, 1], [h, 1], [w, 1], [l, 3] All 1 tests passed
Starting to ❤️ Zig.
Memento on
HashMap
: a dynamic key/value data store.It can be used as a :
Set
: a collection of unique values. You set the value tovoid
in the constructor, and pass an empty tuple{}
when assigning values. Et voilà!HashMap
Memory management: must be initialised with an
allocator
and de-initialised withdeinit()
Common operations:
put(key, value)
- Adds or updates an entryfetchPut(key, value)
- puts a value, returning a value if there was previously a value for that key.get(key)
- Retrieves a valuecontains(key)
- Checks if key existsremove(key)
- Removes an entrycount()
- Returns number of entriesclearAndFree()
- Removes all entries and frees memoryIteration:
keyIterator()
- over keysvalueIterator()
- over valuesiterator()
- Iterate over key-value pairsError handling:
put()
can fail with allocation errors, so usetry
. Other operations likeget()
,contains()
don't return errors.Type of keys:
AutoHashMap
StringHashMap
AutoHashMap: the key is an integer
A Set: the value is
void
.StringHashMap: the key is a string
❗
AutoHashMap
does not support slices as keys, thusStringHashMap
.Custom HashMap
Suppose we want to use a
User
struct with two fields:id: u32
and aname: []const u8
as your "key".How to proceed?
Since we cannot use slices with AutoHashMap, we need to build a custom "context" with two functions:
hash
function that generates a unique hash for the keyeql
function that defines when two keys should be considered equalWe declare these in a "context" struct so that Zig knows:
In the example below, we use Case-Insensitive String Matching. you make a hash from the two fields of User, the id and the name.
We want to treat as equal uppercased and lowercased; "Alice" and "alice" will represent the same entry. This means that the two entries below are equal:
Then if you add successively, in this order:
the HasMap will contain
(u1, 20)
, keeping the original key ("alice") but updating the value.