fix: type recursive mergesort for comparable items (#15406)

Accept any iterable of mutually comparable items and return a new list.
Part of #15234
This commit is contained in:
Columbus Labs
2026-09-23 08:10:19 +02:00
committed by GitHub
parent 2c3bcdda4e
commit cce4d26388
2 changed files with 38 additions and 13 deletions
+35 -13
View File
@@ -1,12 +1,23 @@
"""A merge sort which accepts an array as input and recursively
splits an array in half and sorts and combines them.
"""A merge sort which accepts comparable items and recursively
splits them in half, then sorts and combines the halves.
https://en.wikipedia.org/wiki/Merge_sort
"""
"""https://en.wikipedia.org/wiki/Merge_sort """
from collections.abc import Iterable
from typing import Protocol
def merge(arr: list[int]) -> list[int]:
"""Return a sorted array.
class Comparable(Protocol):
def __lt__(self, other: object, /) -> bool: ...
def merge[T: Comparable](collection: Iterable[T]) -> list[T]:
"""Return a new list of ``collection`` sorted in ascending order.
The input is copied, so the original iterable is left unchanged.
Items must be mutually comparable with ``<``.
>>> merge([10,9,8,7,6,5,4,3,2,1])
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> merge([1,2,3,4,5,6,7,8,9,10])
@@ -17,19 +28,30 @@ def merge(arr: list[int]) -> list[int]:
[100]
>>> merge([])
[]
>>> merge(["c", "a", "b"])
['a', 'b', 'c']
>>> merge([2.5, -1, 0.0])
[-1, 0.0, 2.5]
>>> values = [3, 1, 2]
>>> merge(values)
[1, 2, 3]
>>> values
[3, 1, 2]
>>> merge(("b", "c", "a"))
['a', 'b', 'c']
>>> merge([1, "a"])
Traceback (most recent call last):
...
TypeError: '<' not supported between instances of 'int' and 'str'
"""
arr = list(collection)
if len(arr) > 1:
middle_length = len(arr) // 2 # Finds the middle of the array
left_array = arr[
:middle_length
] # Creates an array of the elements in the first half.
right_array = arr[
middle_length:
] # Creates an array of the elements in the second half.
# Sort each half into a new list, then combine those halves in ``arr``.
left_array = merge(arr[:middle_length])
right_array = merge(arr[middle_length:])
left_size = len(left_array)
right_size = len(right_array)
merge(left_array) # Starts sorting the left.
merge(right_array) # Starts sorting the right
left_index = 0 # Left Counter
right_index = 0 # Right Counter
index = 0 # Position Counter
+3
View File
@@ -41,6 +41,7 @@ from sorts.pancake_sort import pancake_sort
from sorts.patience_sort import patience_sort
from sorts.quick_sort import quick_sort
from sorts.recursive_insertion_sort import rec_insertion_sort
from sorts.recursive_mergesort_array import merge
from sorts.reversort import reversort
from sorts.selection_sort import selection_sort
from sorts.shell_sort import shell_sort
@@ -70,6 +71,7 @@ SORTS = (
heap_sort,
insertion_sort,
iter_merge_sort,
merge,
merge_sort,
odd_even_sort,
pancake_sort,
@@ -140,6 +142,7 @@ def test_rec_insertion_sort(case) -> None:
exchange_sort,
gnome_sort,
insertion_sort,
merge,
merge_sort,
odd_even_sort,
pancake_sort,