From 44ddeb192f5621cd56f1857520c6ae3f2219123a Mon Sep 17 00:00:00 2001 From: andrewkraevskii Date: Tue, 7 Oct 2025 20:47:32 +0300 Subject: [PATCH 1/2] Add `std.mem.collapseRepeatsAll`. --- lib/std/mem.zig | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index ed48132d9a67..01f63c24c259 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4141,6 +4141,42 @@ test collapseRepeats { try testCollapseRepeats("//a///a////", '/', "/a/a/"); } +/// Collapse consecutive duplicates into one entry. +/// +/// See also `collapseRepeats` +pub fn collapseRepeatsAll(comptime T: type, slice: []T) []T { + if (slice.len == 0) return slice; + + var write_index: usize = 1; + for (slice[0 .. slice.len - 1], slice[1..]) |elem, next| { + if (elem != next) { + slice[write_index] = next; + write_index += 1; + } + } + return slice[0..write_index]; +} + +test collapseRepeatsAll { + try std.testing.expectEqualSlices(u8, &.{}, collapseRepeatsAll(u8, &.{})); + { + var array: [1]u8 = .{0}; + try std.testing.expectEqualSlices(u8, &.{0}, collapseRepeatsAll(u8, &array)); + } + { + var array: [2]u8 = .{ 0, 0 }; + try std.testing.expectEqualSlices(u8, &.{0}, collapseRepeatsAll(u8, &array)); + } + { + var array: [2]u8 = .{ 0, 1 }; + try std.testing.expectEqualSlices(u8, &.{ 0, 1 }, collapseRepeatsAll(u8, &array)); + } + { + var array: [10]u8 = .{ 1, 0, 1, 1, 10, 10, 10, 0, 0, 0 }; + try std.testing.expectEqualSlices(u8, &.{ 1, 0, 1, 10, 0 }, collapseRepeatsAll(u8, &array)); + } +} + /// Calculate the size needed in an output buffer to perform a replacement. /// The needle must not be empty. pub fn replacementSize(comptime T: type, input: []const T, needle: []const T, replacement: []const T) usize { From 7712d03491a1511fa8e0d1714b1100cd6c9e0d3b Mon Sep 17 00:00:00 2001 From: andrewkraevskii Date: Tue, 7 Oct 2025 20:47:32 +0300 Subject: [PATCH 2/2] Clarify docs for collapseRepeats{Len}. Makes it clear what only passed element will be deduplicated. --- lib/std/mem.zig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 01f63c24c259..ae6918470964 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4103,7 +4103,9 @@ pub fn replaceScalar(comptime T: type, slice: []T, match: T, replacement: T) voi } } -/// Collapse consecutive duplicate elements into one entry. +/// Collapse all consecutive occurrences of `elem` into one entry. +/// +/// See also `collapseRepeatsAll` pub fn collapseRepeatsLen(comptime T: type, slice: []T, elem: T) usize { if (slice.len == 0) return 0; var write_idx: usize = 1; @@ -4117,7 +4119,9 @@ pub fn collapseRepeatsLen(comptime T: type, slice: []T, elem: T) usize { return write_idx; } -/// Collapse consecutive duplicate elements into one entry. +/// Collapse all consecutive occurrences of `elem` into one entry. +/// +/// See also `collapseRepeatsAll` pub fn collapseRepeats(comptime T: type, slice: []T, elem: T) []T { return slice[0..collapseRepeatsLen(T, slice, elem)]; }