fix(arrays): stop fill from growing the array on reversed spans
fill rebuilt the array as array[:start] + fill + array[end:]. When start came after end those two slices overlapped, duplicating the shared elements and growing the array while writing no value. Normalize start and end into [0, length] and fill in place with an index loop so an empty span is a no-op and the length stays fixed.
This commit is contained in:
1 parent
b129d1f04f
commit
442a17b572
2 files changed
+19
-6
No files matched your search
+11
-6
@@ -531,13 +531,18 @@ def fill(
|
|||||||
|
|
||||||
.. versionadded:: 3.1.0
|
.. versionadded:: 3.1.0
|
||||||
"""
|
"""
|
||||||
if end is None:
|
length = len(array)
|
||||||
end = len(array)
|
|
||||||
else:
|
|
||||||
end = min(end, len(array))
|
|
||||||
|
|
||||||
# Use this style of assignment so that `array` is mutated.
|
if end is None:
|
||||||
array[:] = array[:start] + [value] * len(array[start:end]) + array[end:] # type: ignore
|
end = length
|
||||||
|
|
||||||
|
# Normalize to ``[0, length]``, negatives as slicing does, and fill in
|
||||||
|
# place so the length stays fixed.
|
||||||
|
start = max(length + start, 0) if start < 0 else min(start, length)
|
||||||
|
end = max(length + end, 0) if end < 0 else min(end, length)
|
||||||
|
|
||||||
|
for index in range(start, end):
|
||||||
|
array[index] = value # type: ignore
|
||||||
return array # type: ignore
|
return array # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,14 @@ def test_duplicates(case, expected):
|
|||||||
(([1, 2, 3, 4, 5], 0, 0, 5), [0, 0, 0, 0, 0]),
|
(([1, 2, 3, 4, 5], 0, 0, 5), [0, 0, 0, 0, 0]),
|
||||||
(([1, 2, 3, 4, 5], 0, 0, 8), [0, 0, 0, 0, 0]),
|
(([1, 2, 3, 4, 5], 0, 0, 8), [0, 0, 0, 0, 0]),
|
||||||
(([1, 2, 3, 4, 5], 0, 0, -1), [0, 0, 0, 0, 5]),
|
(([1, 2, 3, 4, 5], 0, 0, -1), [0, 0, 0, 0, 5]),
|
||||||
|
# start after end must be a no-op and must not grow the array.
|
||||||
|
(([1, 2, 3, 4], "x", 4, 1), [1, 2, 3, 4]),
|
||||||
|
(([1, 2, 3, 4, 5], 0, 3, 2), [1, 2, 3, 4, 5]),
|
||||||
|
# negative start supported the same way slicing does.
|
||||||
|
(([1, 2, 3, 4, 5], 0, -2), [1, 2, 3, 0, 0]),
|
||||||
|
(([1, 2, 3, 4, 5], 0, -2, -1), [1, 2, 3, 0, 5]),
|
||||||
|
# reversed negative span is a no-op, not an array-growing overlap.
|
||||||
|
(([1, 2, 3], "x", -1, -2), [1, 2, 3]),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_fill(case, expected):
|
def test_fill(case, expected):
|
||||||
|
|||||||
Reference in new issue
Block a user