I also assumed that the key determination was the slow part of the sort, which is expected with such a relatively small list size (50k). This answer's approach takes the solution of crafting an intermediate list of just the keys and the object reference. This can be quantified and progress can be shown after each object has its key determined. For this demonstration this was made slow by using a key routine with a 100ms sleep inside of it.
At the end, the real sort, will hopefully be able to be run extremely quickly as the keys have all been precalculated.
#!/usr/bin/python
import time
import random
from operator import attrgetter, itemgetter
class Custom:
def __init__(self):
self._key = random.randint(1,50000)
@property
def key(self):
# print('slow key')
time.sleep(0.1)
return self._key
def __repr__(self):
return f"Custom(key={self._key})"
mylist = [Custom() for i in range(40)]
print(mylist)
mylist2 = []
display_inc = 5
display = 0
for x, ele in enumerate(mylist):
mylist2.append((ele.key,ele))
if x/len(mylist) * 100 >= display:
print(f"{display}% done")
# stop displaying after 90
if display >= 90:
display = 110
display += display_inc
print("95% done")
mylist2.sort(key=itemgetter(0))
mylist = [i[1] for i in mylist2]
print("100% done")
print(mylist)
returns
$ python slowsort.py
[Custom(key=22549), Custom(key=5431), Custom(key=8895), Custom(key=10837), Custom(key=12652), Custom(key=43897), Custom(key=24724), Custom(key=16014), Custom(key=46022), Custom(key=25979), Custom(key=45115), Custom(key=45442), Custom(key=42306), Custom(key=17611), Custom(key=25113), Custom(key=12924), Custom(key=21902), Custom(key=1661), Custom(key=6475), Custom(key=41993), Custom(key=40334), Custom(key=44407), Custom(key=20747), Custom(key=7635), Custom(key=38258), Custom(key=45187), Custom(key=13048), Custom(key=18952), Custom(key=46592), Custom(key=10790), Custom(key=24978), Custom(key=5349), Custom(key=47924), Custom(key=12413), Custom(key=7147), Custom(key=17528), Custom(key=3035), Custom(key=16639), Custom(key=17059), Custom(key=25630)]
0% done
5% done
10% done
15% done
20% done
25% done
30% done
35% done
40% done
45% done
50% done
55% done
60% done
65% done
70% done
75% done
80% done
85% done
90% done
95% done
100% done
[Custom(key=1661), Custom(key=3035), Custom(key=5349), Custom(key=5431), Custom(key=6475), Custom(key=7147), Custom(key=7635), Custom(key=8895), Custom(key=10790), Custom(key=10837), Custom(key=12413), Custom(key=12652), Custom(key=12924), Custom(key=13048), Custom(key=16014), Custom(key=16639), Custom(key=17059), Custom(key=17528), Custom(key=17611), Custom(key=18952), Custom(key=20747), Custom(key=21902), Custom(key=22549), Custom(key=24724), Custom(key=24978), Custom(key=25113), Custom(key=25630), Custom(key=25979), Custom(key=38258), Custom(key=40334), Custom(key=41993), Custom(key=42306), Custom(key=43897), Custom(key=44407), Custom(key=45115), Custom(key=45187), Custom(key=45442), Custom(key=46022), Custom(key=46592), Custom(key=47924)]
For some reason if the actual sort on the precalculated keys were slow, then you could partition the list into smaller lists, then resorted into one bigger list but that's kinda messy, so I would want to understand if that would be necessary. Hopefully the significant slowness is in the key generation.
Foo.x
, but there is actually function call and a fair amount of processing involved in determiningx
. Caching the result is a good idea.key=Foo.x
. Assuming this is pure, if this is called more than once on the sameFoo
object during the program, the computation time may be reduced via caching or similar methods.