Skip to content

Commit

Permalink
renew project
Browse files Browse the repository at this point in the history
  • Loading branch information
linjing-lab committed Nov 10, 2022
1 parent 809417e commit 016670c
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 54 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ As you can see, I create a core function to drive keyword sorting just by openin
!pip install sortingx # in jupyter
pip install sortingx # in cmd
```
sortingx can do whatever `list.sort()` do, and support more methods.
sortingx can do whatever `list.sort()` do, and support more methods and more data types.

explain:
- sortingx-1.1.0 is the first version aligned with the `list.sort()` usage method.
- sortingx-1.1.1 is the first stable version accelerated with typing_extensions.
- sortingx-1.1.2 is the first stable version that has a return value and extends the iterable data types.

## LICENSE

Expand Down
1 change: 1 addition & 0 deletions README_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
|--|--|--|--|
|v1.1.0|`pip install sortingx==1.1.0`|Write in Python with Typing||
|v1.1.1|`pip install sortingx==1.1.1`|Complete Typing and Accelerate||
|v1.1.2|`pip install sortingx==1.1.2`|Support More Iterative Data Types||
|v2.0.0|`pip install sortingx==2.0.0`|Rely on Cython||
|v3.0.0|`pip install sortingx==3.0.0`|Restuct with C++||
|v4.0.0|`pip install sortingx==4.0.0`|Rust with PyO3||
Expand Down
2 changes: 1 addition & 1 deletion sortingx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@

from .sorting import bubble, insert, shell, heap, quick, merge

__version__ = '1.1.1'
__version__ = '1.1.2'

assert sys.version_info >= (3, 7, 0)
13 changes: 9 additions & 4 deletions sortingx/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@

from ._typing import Iterable, Callable, Optional, _T, SupportsRichComparison

def generate(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None) -> list:
compare = list(map(key, array)) if key != None else array
compare = ([[value] for value in compare] if compare and compare[0] is not list else compare) if key != None else array
def generate(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None) -> list:
compare = list(map(key, __iterable)) if key != None else __iterable
compare = ([[value] for value in compare] if (compare and not isinstance(compare[0], Iterable)) else compare) if key != None else __iterable
return compare

def core(left: Iterable[_T], right: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> bool:
Expand All @@ -31,4 +31,9 @@ def core(left: Iterable[_T], right: Iterable[_T], key: Optional[Callable[[_T], S
return True
elif left[index] < right[index] and not reverse:
return False
return False
return False

def convert(__iterable: Iterable[_T]) -> list:
if isinstance(__iterable, (tuple, str, set, dict)):
return list(__iterable)
return __iterable
109 changes: 61 additions & 48 deletions sortingx/sorting.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,39 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from ._utils import core, generate
from ._utils import core, generate, convert
from ._typing import Iterable, Callable, Optional, _T, SupportsRichComparison

def bubble(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> None:
def bubble(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> list:
'''
:param array: iterable data.
:param __iterable: iterable data.
:param key: callable function, for example: key=lambda x: x[1], key=lambda x: (x[0], x[1]).
:param reverse: whether to use descending order. The default is ascending order.
'''
compare = generate(array, key)
for i in range(len(array) - 1):
__iterable = convert(__iterable)
compare = generate(__iterable, key)
for i in range(len(__iterable) - 1):
flag = False # early stop by adding a bool value named flag
for j in range(len(array) - i - 1):
for j in range(len(__iterable) - i - 1):
if core(compare[j], compare[j + 1], key, reverse):
array[j], array[j + 1] = array[j + 1], array[j]
__iterable[j], __iterable[j + 1] = __iterable[j + 1], __iterable[j]
flag = True
if key != None:
compare[j], compare[j + 1] = compare[j + 1], compare[j]
if not flag:
break
return __iterable

def insert(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> None:
def insert(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> list:
'''
:param array: iterable data.
:param __iterable: iterable data.
:param key: callable function, for example: key=lambda x: x[1], key=lambda x: (x[0], x[1]).
:param reverse: whether to use descending order. The default is ascending order.
'''
compare = generate(array, key)
for index in range(1, len(array)):
keyc, keya = compare[index], array[index]
__iterable = convert(__iterable)
compare = generate(__iterable, key)
for index in range(1, len(__iterable)):
keyc, keya = compare[index], __iterable[index]
low, high = 0, index - 1
while low <= high: # sequence conforming to monotonicity
mid = (low + high) // 2
Expand All @@ -50,45 +53,50 @@ def insert(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichCompari
else:
high = mid - 1
for pre in range(index, low, -1): # from back to front
array[pre] = array[pre - 1]
__iterable[pre] = __iterable[pre - 1]
if key != None:
compare[pre] = compare[pre - 1]
array[low] = keya
__iterable[low] = keya
if key != None:
compare[low] = keyc
return __iterable

def shell(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> None:
def shell(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> list:
'''
:param array: iterable data.
:param __iterable: iterable data.
:param key: callable function, for example: key=lambda x: x[1], key=lambda x: (x[0], x[1]).
:param reverse: whether to use descending order. The default is ascending order.
'''
compare = generate(array, key)
length = len(array)
__iterable = convert(__iterable)
compare = generate(__iterable, key)
length = len(__iterable)
gap = 1
while gap < length / 3:
gap = int(3 * gap + 1)
while gap >= 1:
for index in range(gap, length):
next = index
while next >= gap and core(compare[next - gap], compare[next], key, reverse):
array[next], array[next - gap] = array[next - gap], array[next]
__iterable[next], __iterable[next - gap] = __iterable[next - gap], __iterable[next]
if key != None:
compare[next], compare[next - gap] = compare[next - gap], compare[next]
next -= gap
gap = int(gap / 3)
return __iterable


def heap(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> None:
def heap(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> list:
'''
:param array: iterable data.
:param __iterable: iterable data.
:param key: callable function, for example: key=lambda x: x[1], key=lambda x: (x[0], x[1]).
:param reverse: whether to use descending order. The default is ascending order.
'''
compare = generate(array, key)
__iterable = convert(__iterable)
compare = generate(__iterable, key)
def build(root: int, end: int) -> None:
'''
:param root: cursor indicating the root node (int).
:param end: cursor indicating the end of the array (int).
:param end: cursor indicating the end of the __iterable (int).
'''
piv = root
left = 2 * root + 1
Expand All @@ -98,27 +106,29 @@ def build(root: int, end: int) -> None:
if right < end and core(compare[right], compare[piv], key, reverse):
piv = right
if piv != root:
array[root], array[piv] = array[piv], array[root]
__iterable[root], __iterable[piv] = __iterable[piv], __iterable[root]
if key != None:
compare[root], compare[piv] = compare[piv], compare[root]
build(piv, end)

length = len(array)
length = len(__iterable)
for root in range(length // 2 - 1 , -1, -1):
build(root, length)
for end in range(length - 1, 0, -1):
array[0], array[end] = array[end], array[0]
__iterable[0], __iterable[end] = __iterable[end], __iterable[0]
if key != None:
compare[0], compare[end] = compare[end], compare[0]
build(0, end)
return __iterable

def quick(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> None:
def quick(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> list:
'''
:param array: iterable data.
:param __iterable: iterable data.
:param key: callable function, for example: key=lambda x: x[1], key=lambda x: (x[0], x[1]).
:param reverse: whether to use descending order. The default is ascending order.
'''
compare = generate(array, key)
__iterable = convert(__iterable)
compare = generate(__iterable, key)
def solve(l: int, r: int) -> None:
'''
main
Expand All @@ -130,38 +140,40 @@ def solve(l: int, r: int) -> None:

def partition(l: int, r: int) -> int:
'''
:param l: The left cursor of array (int).
:param r: The right cursor of array (int).
:param l: The left cursor of __iterable (int).
:param r: The right cursor of __iterable (int).
'''
val = compare[r]
index = l - 1
for ind in range(l, r):
if core(val, compare[ind], key, reverse):
index += 1
array[index], array[ind] = array[ind], array[index]
__iterable[index], __iterable[ind] = __iterable[ind], __iterable[index]
if key != None:
compare[index], compare[ind] = compare[ind], compare[index]
array[index + 1], array[r] = array[r], array[index + 1]
__iterable[index + 1], __iterable[r] = __iterable[r], __iterable[index + 1]
if key != None:
compare[index + 1], compare[r] = compare[r], compare[index + 1]
return index + 1
solve(0, len(array)-1)
solve(0, len(__iterable)-1)
return __iterable

def merge(array: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> None:
def merge(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> list:
'''
:param array: iterable data.
:param __iterable: iterable data.
:param key: callable function, for example: key=lambda x: x[1], key=lambda x: (x[0], x[1]).
:param reverse: whether to use descending order. The default is ascending order.
'''
compare = generate(array, key)
def merge(low: int, mid: int, high: int) -> None:
__iterable = convert(__iterable)
compare = generate(__iterable, key)
def merg(low: int, mid: int, high: int) -> None:
'''
:param low: The low-side cursor of array (int).
:param mid: The middle-side cursor of array (int).
:param high: The high-side cursor of array (int).
:param low: The low-side cursor of __iterable (int).
:param mid: The middle-side cursor of __iterable (int).
:param high: The high-side cursor of __iterable (int).
'''
left, lc = array[low: mid], compare[low: mid]
right, rc = array[mid: high], compare[mid: high]
left, lc = __iterable[low: mid], compare[low: mid]
right, rc = __iterable[mid: high], compare[mid: high]
i = 0
j = 0
result, store = [], []
Expand All @@ -178,23 +190,24 @@ def merge(low: int, mid: int, high: int) -> None:
store += lc[i:]
result += right[j:]
store += rc[j:]
array[low: high] = result
__iterable[low: high] = result
compare[low: high] = store

def solve() -> None:
'''
main
'''
i = 1
while i < len(array):
while i < len(__iterable):
low = 0
while low < len(array):
while low < len(__iterable):
mid = low + i
high = min(low + 2 * i, len(array))
high = min(low + 2 * i, len(__iterable))
if mid < high:
merge(low, mid, high)
merg(low, mid, high)
low += 2 * i
i *= 2
solve()
return __iterable

__all__ = [bubble, insert, shell, heap, quick, merge]
7 changes: 7 additions & 0 deletions test_typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import sortingx as six

data = {'Alex': 100, 'Jack': 97, 'Peter': 88, 'Li': 98}
print(type(data))
test = sorted(data, reverse=True)
output = six.bubble(data, reverse=True)
print(output, '\n', output == test)

0 comments on commit 016670c

Please sign in to comment.