add replaceRange() function to ArrayList
generalizes functionality of ArrayList.insertSlice() to overwrite a range of elements in the list and to grow or shrink the list as needed to accommodate size difference of the replacing slice and the range of existing elements.
This commit is contained in:
@@ -108,6 +108,33 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
|
||||
mem.copy(T, self.items[i .. i + items.len], items);
|
||||
}
|
||||
|
||||
/// Replace range of elements `list[start..start+len]` with `new_items`
|
||||
/// grows list if `len < new_items.len`. may allocate
|
||||
/// shrinks list if `len > new_items.len`
|
||||
pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void {
|
||||
const after_range = start + len;
|
||||
const range = self.items[start..after_range];
|
||||
|
||||
if (range.len == new_items.len)
|
||||
mem.copy(T, range, new_items)
|
||||
else if (range.len < new_items.len) {
|
||||
const first = new_items[0..range.len];
|
||||
const rest = new_items[range.len..];
|
||||
|
||||
mem.copy(T, range, first);
|
||||
try self.insertSlice(after_range, rest);
|
||||
} else {
|
||||
mem.copy(T, range, new_items);
|
||||
const after_subrange = start + new_items.len;
|
||||
|
||||
for (self.items[after_range..]) |item, i| {
|
||||
self.items[after_subrange..][i] = item;
|
||||
}
|
||||
|
||||
self.items.len -= len - new_items.len;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extend the list by 1 element. Allocates more memory as necessary.
|
||||
pub fn append(self: *Self, item: T) !void {
|
||||
const new_item_ptr = try self.addOne();
|
||||
@@ -335,6 +362,15 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
|
||||
mem.copy(T, self.items[i .. i + items.len], items);
|
||||
}
|
||||
|
||||
/// Replace range of elements `list[start..start+len]` with `new_items`
|
||||
/// grows list if `len < new_items.len`. may allocate
|
||||
/// shrinks list if `len > new_items.len`
|
||||
pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void {
|
||||
var managed = self.toManaged(allocator);
|
||||
try managed.replaceRange(start, len, new_items);
|
||||
self.* = managed.toUnmanaged();
|
||||
}
|
||||
|
||||
/// Extend the list by 1 element. Allocates more memory as necessary.
|
||||
pub fn append(self: *Self, allocator: *Allocator, item: T) !void {
|
||||
const new_item_ptr = try self.addOne(allocator);
|
||||
@@ -657,6 +693,35 @@ test "std.ArrayList.insertSlice" {
|
||||
testing.expect(list.items[0] == 1);
|
||||
}
|
||||
|
||||
test "std.ArrayList.replaceRange" {
|
||||
var arena = std.heap.ArenaAllocator.init(testing.allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const alloc = &arena.allocator;
|
||||
const init = [_]i32{ 1, 2, 3, 4, 5 };
|
||||
const new = [_]i32{ 0, 0, 0 };
|
||||
|
||||
var list_zero = ArrayList(i32).init(alloc);
|
||||
var list_eq = ArrayList(i32).init(alloc);
|
||||
var list_lt = ArrayList(i32).init(alloc);
|
||||
var list_gt = ArrayList(i32).init(alloc);
|
||||
|
||||
try list_zero.appendSlice(&init);
|
||||
try list_eq.appendSlice(&init);
|
||||
try list_lt.appendSlice(&init);
|
||||
try list_gt.appendSlice(&init);
|
||||
|
||||
try list_zero.replaceRange(1, 0, &new);
|
||||
try list_eq.replaceRange(1, 3, &new);
|
||||
try list_lt.replaceRange(1, 2, &new);
|
||||
try list_gt.replaceRange(1, 4, &new);
|
||||
|
||||
testing.expectEqualSlices(i32, list_zero.items, &[_]i32{ 1, 0, 0, 0, 2, 3, 4, 5 });
|
||||
testing.expectEqualSlices(i32, list_eq.items, &[_]i32{ 1, 0, 0, 0, 5 });
|
||||
testing.expectEqualSlices(i32, list_lt.items, &[_]i32{ 1, 0, 0, 0, 4, 5 });
|
||||
testing.expectEqualSlices(i32, list_gt.items, &[_]i32{ 1, 0, 0, 0 });
|
||||
}
|
||||
|
||||
const Item = struct {
|
||||
integer: i32,
|
||||
sub_items: ArrayList(Item),
|
||||
|
||||
Reference in New Issue
Block a user