Skip to content

Commit 25e544b

Browse files
committed
renew project
1 parent f8a933e commit 25e544b

File tree

6 files changed

+77
-53
lines changed

6 files changed

+77
-53
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ explain:
9696
By the way, I didn't complete all the iterative data types, in order to develop a more targeted scenario. If you are **interested** in other iterative data types, please add them in the `convert` function of the `_utils.py` file, for example: bytes, bytearray, range, zip. If you need to deal with `dict_keys`, `dict_values`, `dict_items`, please use `list()` to convert the variables of these data types before using any method of sortingx.
9797

9898
- [sortingx-1.2.2](https://github.com/linjing-lab/sorting-algorithms/tree/v1.2.2) is the package that support `range`, `zip`, `dict_keys`, `dict_values`, `dict_items` additionally, you can choose what suitable data you want to input.
99+
- [sortingx-1.2.3](https://github.com/linjing-lab/sorting-algorithms/tree/v1.2.3) is the package that corrected the situation where elements are equal in `compare`, support more input data, like data as `[['Jack', (98, 100)], ['Bob', (98, 99)], ['Jessi', (98, 97)]]` and key as `lambda x: x[1][0]`.
99100

100101
## LICENSE
101102

Diff for: README_release.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@
1111
|v1.2.0|`pip install sortingx==1.2.0`|Optimize Generate Function's Kernel||
1212
|v1.2.1|`pip install sortingx==1.2.1`|Delete Core Function to Make Builtin First||
1313
|v1.2.2|`pip install sortingx==1.2.2`|Change Convert Function to Make it More Robust||
14+
|v1.2.3|`pip install sortingx==1.2.3`|Add Verify Function to Solve Comparison of Equal||
1415

1516
</div>

Diff for: sortingx/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@
1616

1717
from .sorting import bubble, insert, shell, heap, quick, merge, __all__
1818

19-
__version__ = '1.2.2'
19+
__version__ = '1.2.3'
2020

2121
assert sys.version_info >= (3, 7, 0)

Diff for: sortingx/_utils.py

+9
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ def generate(__iterable: List[_T], key: Optional[Callable[[_T], SupportsRichComp
2525
compare: List[_T] = list(map(key, __iterable)) if key != None else __iterable
2626
return compare
2727

28+
# Verify Elements Are Equal before Comparison.
29+
def verify(compare: List[_T]) -> bool:
30+
'''
31+
:param compare: List[_T], list generated by `generate` with builtin api named `map`.
32+
33+
:return: bool value indicated whether to enter comparison.
34+
'''
35+
return compare.count(compare[0]) == len(compare)
36+
2837
# Uniformly Convert `Iterable` into `List`: Facilitate the Execution of Sorting Algorithms.
2938
def convert(__iterable: Iterable[_T]) -> List[_T]:
3039
'''

Diff for: sortingx/sorting.py

+57-52
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from ._utils import generate, convert
15+
from ._utils import generate, convert, verify
1616
from ._typing import Iterable, Callable, Optional, _T, SupportsRichComparison, List
1717

1818
__all__ = ["bubble", "insert", "shell", "heap", "quick", "merge"]
@@ -27,16 +27,17 @@ def bubble(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichCo
2727
'''
2828
__iterable: List[_T] = convert(__iterable)
2929
compare: List[_T] = generate(__iterable, key)
30-
for i in range(len(__iterable) - 1):
31-
flag: bool = False # early stop by adding a bool value named flag
32-
for j in range(len(__iterable) - i - 1):
33-
if (compare[j] < compare[j + 1] if reverse else compare[j] > compare[j+1]):
34-
__iterable[j], __iterable[j + 1] = __iterable[j + 1], __iterable[j]
35-
if key != None:
36-
compare[j], compare[j + 1] = compare[j + 1], compare[j]
37-
flag: bool = True
38-
if not flag:
39-
break
30+
if compare and not verify(compare):
31+
for i in range(len(__iterable) - 1):
32+
flag: bool = False # early stop by adding a bool value named flag
33+
for j in range(len(__iterable) - i - 1):
34+
if (compare[j] < compare[j + 1] if reverse else compare[j] > compare[j+1]):
35+
__iterable[j], __iterable[j + 1] = __iterable[j + 1], __iterable[j]
36+
if key != None:
37+
compare[j], compare[j + 1] = compare[j + 1], compare[j]
38+
flag: bool = True
39+
if not flag:
40+
break
4041
return __iterable
4142

4243
def insert(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> List[_T]:
@@ -49,24 +50,25 @@ def insert(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichCo
4950
'''
5051
__iterable: List[_T] = convert(__iterable)
5152
compare: List[_T] = generate(__iterable, key)
52-
for index in range(1, len(__iterable)):
53-
keyc: _T = compare[index]
54-
keya: _T = __iterable[index]
55-
low : int = 0
56-
high: int = index - 1
57-
while low <= high: # sequence conforming to monotonicity
58-
mid: int = (low + high) // 2
59-
if (keyc < compare[mid] if reverse else keyc > compare[mid]):
60-
low: int = mid + 1
61-
else:
62-
high: int = mid - 1
63-
for pre in range(index, low, -1): # from back to front
64-
__iterable[pre] = __iterable[pre - 1]
53+
if compare and not verify(compare):
54+
for index in range(1, len(__iterable)):
55+
keyc: _T = compare[index]
56+
keya: _T = __iterable[index]
57+
low : int = 0
58+
high: int = index - 1
59+
while low <= high: # sequence conforming to monotonicity
60+
mid: int = (low + high) // 2
61+
if (keyc < compare[mid] if reverse else keyc > compare[mid]):
62+
low: int = mid + 1
63+
else:
64+
high: int = mid - 1
65+
for pre in range(index, low, -1): # from back to front
66+
__iterable[pre] = __iterable[pre - 1]
67+
if key != None:
68+
compare[pre] = compare[pre - 1]
69+
__iterable[low] = keya
6570
if key != None:
66-
compare[pre] = compare[pre - 1]
67-
__iterable[low] = keya
68-
if key != None:
69-
compare[low] = keyc
71+
compare[low] = keyc
7072
return __iterable
7173

7274
def shell(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> List[_T]:
@@ -79,19 +81,20 @@ def shell(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichCom
7981
'''
8082
__iterable: List[_T] = convert(__iterable)
8183
compare: List[_T] = generate(__iterable, key)
82-
length: int = len(__iterable)
83-
gap: int = 1
84-
while gap < length / 3:
85-
gap: int = int(3 * gap + 1)
86-
while gap >= 1:
87-
for index in range(gap, length):
88-
next: int = index
89-
while next >= gap and (compare[next - gap] < compare[next] if reverse else compare[next - gap] > compare[next]):
90-
__iterable[next], __iterable[next - gap] = __iterable[next - gap], __iterable[next]
91-
if key != None:
92-
compare[next], compare[next - gap] = compare[next - gap], compare[next]
93-
next -= gap
94-
gap: int = int(gap / 3)
84+
if compare and not verify(compare):
85+
length: int = len(__iterable)
86+
gap: int = 1
87+
while gap < length / 3:
88+
gap: int = int(3 * gap + 1)
89+
while gap >= 1:
90+
for index in range(gap, length):
91+
next: int = index
92+
while next >= gap and (compare[next - gap] < compare[next] if reverse else compare[next - gap] > compare[next]):
93+
__iterable[next], __iterable[next - gap] = __iterable[next - gap], __iterable[next]
94+
if key != None:
95+
compare[next], compare[next - gap] = compare[next - gap], compare[next]
96+
next -= gap
97+
gap: int = int(gap / 3)
9598
return __iterable
9699

97100
def heap(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> List[_T]:
@@ -121,15 +124,15 @@ def build(root: int, end: int) -> None:
121124
if key != None:
122125
compare[root], compare[piv] = compare[piv], compare[root]
123126
build(piv, end)
124-
125-
length: int = len(__iterable)
126-
for root in range(length // 2 - 1 , -1, -1):
127-
build(root, length)
128-
for end in range(length - 1, 0, -1):
129-
__iterable[0], __iterable[end] = __iterable[end], __iterable[0]
130-
if key != None:
131-
compare[0], compare[end] = compare[end], compare[0]
132-
build(0, end)
127+
if compare and not verify(compare):
128+
length: int = len(__iterable)
129+
for root in range(length // 2 - 1 , -1, -1):
130+
build(root, length)
131+
for end in range(length - 1, 0, -1):
132+
__iterable[0], __iterable[end] = __iterable[end], __iterable[0]
133+
if key != None:
134+
compare[0], compare[end] = compare[end], compare[0]
135+
build(0, end)
133136
return __iterable
134137

135138
def quick(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> List[_T]:
@@ -168,7 +171,8 @@ def partition(l: int, r: int) -> int:
168171
if key != None:
169172
compare[index + 1], compare[r] = compare[r], compare[index + 1]
170173
return index + 1
171-
solve(0, len(__iterable) - 1)
174+
if compare and not verify(compare):
175+
solve(0, len(__iterable) - 1)
172176
return __iterable
173177

174178
def merge(__iterable: Iterable[_T], key: Optional[Callable[[_T], SupportsRichComparison]]=None, reverse: bool=False) -> List[_T]:
@@ -225,5 +229,6 @@ def solve() -> None:
225229
merg(low, mid, high)
226230
low += 2 * i
227231
i *= 2
228-
solve()
232+
if compare and not verify(compare):
233+
solve()
229234
return __iterable

Diff for: tests/test_equal.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import sortingx
2+
3+
data1 = [['Jack', (98, 100)], ['Bob', (98, 99)], ['Jessi', (98, 97)]]
4+
data2 = [['Jack', (98.1, 100)], ['Bob', (98.1, 99)], ['Jessi', (98.1, 97)]]
5+
data3 = [['Jack', (98.11, 100)], ['Bob', (98.10000000000, 99)], ['Jessi', (98.1100000000000000, 97)]]
6+
7+
print(sortingx.bubble(data1, key=lambda x: x[1][0], reverse=True))
8+
print(sorted(data1, key=lambda x: x[1][0], reverse=True))

0 commit comments

Comments
 (0)