I wrote the following to find the maximum value in a Zig std.AutoHashMap
:
pub fn hashMinMaxValue(comptime K: type, comptime V: type, hash_map: std.AutoHashMap(K, V)) ?struct { min: V, max: V } {
var min: V = undefined;
var max: V = undefined;
var it = hash_map.valueIterator();
if (it.next()) |val| {
min = val.*;
max = val.*;
} else {
return null;
}
while (it.next()) |val| {
min = @min(min, val.*);
max = @max(max, val.*);
}
return .{ .min = min, .max = max };
}
pub fn hashMaxValue(comptime K: type, comptime V: type, hash_map: std.AutoHashMap(K, V)) ?V {
const minMax = hashMinMaxValue(K, V, hash_map);
if (minMax) |v| {
return v.max;
}
return null;
}
Now I'd like to use this with a std.StringHashMap
. So I copy/pasted the code and adjusted it like so:
pub fn strHashMinMaxValue(comptime V: type, hash_map: std.StringHashMap(V)) ?struct { min: V, max: V } {
var min: V = undefined;
var max: V = undefined;
var it = hash_map.valueIterator();
if (it.next()) |val| {
min = val.*;
max = val.*;
} else {
return null;
}
while (it.next()) |val| {
min = @min(min, val.*);
max = @max(max, val.*);
}
return .{ .min = min, .max = max };
}
pub fn strHashMaxValue(comptime V: type, hash_map: std.StringHashMap(V)) ?V {
const minMax = strHashMinMaxValue(V, hash_map);
if (minMax) |v| {
return v.max;
}
return null;
}
This feels a little gross. Is there a good way to share logic between these? Moreover, since I only need the max value, is there a way to mark the generic key type K
as "don't care"?
You need to use anytype
. For example:
fn find_max_value(comptime V: type, hash_map: anytype) ?V {
var max: V = undefined;
var it = hash_map.valueIterator();
if (it.next()) |value| {
max = value.*;
}
else {
return null;
}
while (it.next()) |value| {
max = @max(max, value.*);
}
return max;
}
This works for both AutoHashMap
and StringHashMap
.
Take a look at Generic Data Structures in the Zig documentation for more information.