-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
Description
Feature or enhancement
Proposal:
def sorted(iterable, /, *, key=None, keylist=None, reverse=False):
...keylist is an extension that allows providing keys to list.sort that will be used for sorting.
This allows bypassing key generation via callable key argument or using zip with itemgetter in situations where possible.
The above are all relatively expensive operations, thus performance gain is non-trivial.
keylist accepts list, which will be mutated as part of sorting.
To prevent mutation of the input (or to supply arbitrary iterable), make a copy:
a.sort(keylist=list(my_keys))List of examples and benchmarks is present in discourse thread.
TLDR: These are 3 main takeaways:
- Faster
argsortwithout needing to use dunder method
# Current one best way
indices = sorted(range(N), key=seq.__getitem__) # 32 ms (100K ints)
# After this:
indices = sorted(range(N), keylist=list(seq)) # 26 ms (100K ints)- Non-trivial performance for
dictsorting (or any other problem that is of the same nature)
Performance improvement against current alternative is 2-5x.
keys = list(d)
values = list(d.values())
values.sort(keylist=keys)- Generally better performance whenever
keylistis ready or faster ways to construct it are available
values = list(range(100_000))
%timeit list(map(lambda x: x % 10, l)) # 7.71 ms (What happens via `key`)
%timeit [x % 10 for x in l] # 3.23 ms (If could be done manually)In short, it provides an entry into list.sort function that makes it possible to take faster path in many cases where input list is not the same as sort keys.
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
https://discuss.python.org/t/allow-sorted-to-take-list-for-key-argument/105106