@@ -173,6 +173,8 @@ def sorted_no_duplicates(
173173 key : Callable [[T ], K ] = lambda x : x ,
174174 recursive_key : Callable [[K ], K ] | None = None ,
175175) -> list [T ]:
176+ from functools import cmp_to_key
177+
176178 # Order functions
177179 def type_order (x : Any , y : Any ) -> int :
178180 """
@@ -233,86 +235,30 @@ def order(x: Any, y: Any) -> int:
233235 return int (x < y ) - int (x > y ) # type: ignore
234236 except TypeError :
235237 # These types cannot be compared, so fallback to string comparison.
236- return str (x ) < str (y )
238+ return int ( str (x ) < str (y )) - int ( str ( x ) > str ( y ) )
237239
238- # Sort functions, custom implementation needed for efficient recursive ordering
239- # of values that have different types
240- def insertion_sort (list_t : list [T ], start : int , end : int ) -> list [T ]:
241- """
242- Insertion sort
243- :param list_t: list to sort
244- :param start: start of range to sort
245- :param end: end of range to sort
246- :return: the list itself
247- """
248- for i in range (start + 1 , end ):
249- j = i - 1
250- item = list_t [i ]
251- item_key = key (item )
252- while j >= start and order (key (list_t [j ]), item_key ) < 0 :
253- list_t [j + 1 ] = list_t [j ]
254- j -= 1
255- list_t [j + 1 ] = item
256- return list_t
257-
258- def merge (to_list : list [T ], from_list : list [T ], start : int , middle : int , end : int ):
259- """
260- Merge two sorted sublist to sorted list
261-
262- :param to_list: output list
263- :param from_list: input list
264- :param start: start of first half
265- :param middle: end of first half, start of second half
266- :param end: end of second half
267- :return: No return value
268- """
269- i , j , k = start , middle , start
270- while i < middle and j < end :
271- if order (key (from_list [i ]), key (from_list [j ])) > 0 :
272- to_list [k ] = from_list [i ]
273- i += 1
274- else :
275- to_list [k ] = from_list [j ]
276- j += 1
277- k += 1
278- if i < middle :
279- to_list [k :end ] = from_list [i :middle ]
280- else :
281- to_list [k :end ] = from_list [j :end ]
240+ # Use Python's built-in sorted with cmp_to_key for performance.
241+ # We negate the order result because `order` returns 1 for x < y,
242+ # but cmp expects -1 for x < y.
243+ wrapped_key = cmp_to_key (lambda x , y : - order (x , y ))
282244
283- def timsort (list_t : list [T ], timgroup : int = 32 ) -> list [T ]:
284- """
285- Time sort algorithm
286- :param list_t: the modifiable list to sort
287- :param timgroup: the number of elements to sort with insertion sort
288- :return: The sort list
289- """
290- len_list_t = len (list_t )
291- for i in range (0 , len_list_t , timgroup ):
292- insertion_sort (list_t , i , min (i + timgroup , len_list_t ))
293- copy = list (list_t )
294- while timgroup < len_list_t :
295- for start in range (0 , len_list_t , 2 * timgroup ):
296- middle = min (len_list_t , start + timgroup )
297- end = min (len_list_t , start + 2 * timgroup )
298- merge (list_t , copy , start , middle , end )
299- list_t , copy = copy , list_t
300- timgroup *= 2
301- return copy
302-
303- # Sort and filterout duplicates
304- first , last_key , no_dup , list_iter = True , None , [], list (iterable )
305- for v in timsort (list_iter ):
306- if not first :
307- key_v = key (v )
308- if order (key_v , last_key ) == 0 :
309- continue
310- else :
311- no_dup .append (v )
312- last_key = key_v
313- else :
314- first , last_key = False , key (v )
245+ sorted_iter = sorted (iterable , key = lambda x : wrapped_key (key (x )))
246+
247+ # Filter out duplicates
248+ no_dup = []
249+ if not sorted_iter :
250+ return no_dup
251+
252+ last_v = sorted_iter [0 ]
253+ last_key_val = key (last_v )
254+ no_dup .append (last_v )
255+
256+ for v in sorted_iter [1 :]:
257+ key_v = key (v )
258+ if order (key_v , last_key_val ) != 0 :
315259 no_dup .append (v )
260+ last_key_val = key_v
261+
316262 return no_dup
317263
318264
0 commit comments