authorgravatar for mpopov@fastmail.fmMikhail Popov <mpopov@fastmail.fm> 2021-10-22 14:38:08+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-27 21:22:00+02:00
log100b8a244cdbcd16669e6b81ab82d6a628559e22
tree9ceea7c580e5457487e129c237ef472db65f33ab
parentdddbd2f511f505ad4018ba007f065ea2b4ec8f79

Add std.mem.minMax() and std.mem.IndexOfMinMax()

For finding the minimum and maximum values (and indices) in a slice in a single pass.

1 files changed, 48 insertions(+), 0 deletions(-)

lib/std/mem.zig+48
......@@ -2174,6 +2174,26 @@ test "mem.max" {
21742174 try testing.expectEqual(max(u8, "g"), 'g');
21752175}
21762176
2177/// Finds the smallest and largest number in a slice. O(n).
2178/// Returns an anonymous struct with the fields `min` and `max`.
2179/// `slice` must not be empty.
2180pub fn minMax(comptime T: type, slice: []const T) struct { min: T, max: T } {
2181 assert(slice.len > 0);
2182 var minVal = slice[0];
2183 var maxVal = slice[0];
2184 for (slice[1..]) |item| {
2185 minVal = math.min(minVal, item);
2186 maxVal = math.max(maxVal, item);
2187 }
2188 return .{ .min = minVal, .max = maxVal };
2189}
2190
2191test "mem.minMax" {
2192 try testing.expectEqual(minMax(u8, "abcdefg"), .{ .min = 'a', .max = 'g' });
2193 try testing.expectEqual(minMax(u8, "bcdefga"), .{ .min = 'a', .max = 'g' });
2194 try testing.expectEqual(minMax(u8, "a"), .{ .min = 'a', .max = 'a' });
2195}
2196
21772197/// Returns the index of the smallest number in a slice. O(n).
21782198/// `slice` must not be empty.
21792199pub fn indexOfMin(comptime T: type, slice: []const T) usize {
......@@ -2216,6 +2236,34 @@ test "mem.indexOfMax" {
22162236 try testing.expectEqual(indexOfMax(u8, "a"), 0);
22172237}
22182238
2239/// Finds the indices of the smallest and largest number in a slice. O(n).
2240/// Returns an anonymous struct with the fields `index_min` and `index_max`.
2241/// `slice` must not be empty.
2242pub fn indexOfMinMax(comptime T: type, slice: []const T) struct { index_min: usize, index_max: usize } {
2243 assert(slice.len > 0);
2244 var minVal = slice[0];
2245 var maxVal = slice[0];
2246 var minIdx: usize = 0;
2247 var maxIdx: usize = 0;
2248 for (slice[1..]) |item, i| {
2249 if (item < minVal) {
2250 minVal = item;
2251 minIdx = i + 1;
2252 }
2253 if (item > maxVal) {
2254 maxVal = item;
2255 maxIdx = i + 1;
2256 }
2257 }
2258 return .{ .index_min = minIdx, .index_max = maxIdx };
2259}
2260
2261test "mem.indexOfMinMax" {
2262 try testing.expectEqual(indexOfMinMax(u8, "abcdefg"), .{ .index_min = 0, .index_max = 6 });
2263 try testing.expectEqual(indexOfMinMax(u8, "gabcdef"), .{ .index_min = 1, .index_max = 0 });
2264 try testing.expectEqual(indexOfMinMax(u8, "a"), .{ .index_min = 0, .index_max = 0 });
2265}
2266
22192267pub fn swap(comptime T: type, a: *T, b: *T) void {
22202268 const tmp = a.*;
22212269 a.* = b.*;