A válasz, mint ahogy sok esetben, most is az, hogy attól függ. Ugyanis a sorted() beépített függvény egy iterálható objektumot fogad és a rendezett elemeket egy listában adja vissza. Ha az argumentumként átadott iterálható objektum konténer, akkor az a sorted() hívása után változatlan marad. Ha a rendezni kívánt elemek egy listában (list típusú konténerben) vannak, vagy egy iterálható objektumból listában gyűjtjük össze azokat, akkor a rendezést a lista sort() metódusával is elvégezhetjük. Ilyenkor a rendezés helyben (in-place) történik, ami azt jelenti, hogy – ellentétben a sorted() függvény használatával – az eredeti elemsorrend a rendezés után nem áll rendelkezésre (kivéve persze, ha a sort() metódus hívása előtt a lista elemeit egy másik sorozat típusú konténerbe nem „mentjük”)
Tehát a választás első szempontja, hogy szükséges-e, hogy a rendezetlen elemsorozat megmaradjon. Ha igen, akkor célszerű a sorted() választása.
Másik szempont a memóriaigény. A sorted(), mivel az eredeti adatsorozat is megmarad és létrejön egy új rendezett lista, nyilván több memóriát igényel, mint a helyben rendezett lista.
És végül az is fontos lehet, hogy futási időben hogy teljesít a két módszer.
Ennek vizsgálatához az alább látható három függvényt készítettük. Az első egy iterálható objektumot fogad, és ennek elemeit a sorted() függvény segítségével rendezi. A második szintén egy tetszőleges iterálható objektumot fogad, de utána ebből egy listát állít elő, amit a sort() metódussal rendez. Az előbbiektől eltérően a harmadik függvénynek egy listát kell átadni, amelynek elemei közvetlenül, helyben lesznek rendezve a sort() metódus meghívása után.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
from timeit import timeit from random import randint from typing import Iterable def sort_iterable_using_sorted(unsorted_data: Iterable) -> list: """Az argumentumként megadott iterálható objektum elemeit rendezi növekvő sorrendbe a sorted() beépített függvény használatával. Ha az argumentum konténerobjektum, annak elemei változatlan sorrendben maradnak. """ return sorted(unsorted_data) def sort_iterable_using_list_sort(unsorted_data: Iterable) -> list: """Az argumentumként megadott iterálható objektum elemeit rendezi növekvő sorrendbe úgy, hogy az argumentumból az elemek egy list konténerbe kerülnek, és e lista sort() metódusának használatával rendeződnek. Ha az argumentum konténerobjektum, annak elemei változatlan sorrendben maradnak. """ lst = list(unsorted_data) lst.sort() return lst def sort_list_using_list_sort(unsorted_data: list) -> list: """Az argumentumként megadott lista elemeit rendezi növekvő sorrendbe a sort() metódus használatával. A rendezés helyben történik, vagyis az argumentum elemei eredeti sorrendjüket nem őrzik meg.""" lst = unsorted_data lst.sort() return lst # TESZT exec_count = 1000 for n in [10 * 10 ** i for i in range(5)]: unsorted_items: tuple = tuple(randint(1, 5000) for _ in range(n)) # n db véletlen egész előállítása. unsorted_list: list = list(unsorted_items) t_using_sorted = timeit('sort_iterable_using_sorted(unsorted_items)', globals=globals(), number=exec_count) t_using_list_sort = timeit('sort_iterable_using_list_sort(unsorted_items)', globals=globals(), number=exec_count) t_list_sort_passing_list = timeit('sort_list_using_list_sort(unsorted_list)', globals=globals(), number=exec_count) # Kiírjuk a list.sort() metódust használó rendezések futási idejének és a sorted() függvény használatával elért rendezési idő arányát # a rendezendő elemszám függvényében. print('Rendezendő elemek száma = {:<8}, {:.1%}, {:.1%}'.format(n, t_using_list_sort / t_using_sorted, t_list_sort_passing_list / t_using_sorted)) # Eredmények: # Rendezendő elemek száma = 10 , 92.4%, 39.7% # Rendezendő elemek száma = 100 , 97.6%, 15.6% # Rendezendő elemek száma = 1000 , 95.5%, 4.4% # Rendezendő elemek száma = 10000 , 99.9%, 4.1% # Rendezendő elemek száma = 100000 , 97.8%, 4.3% |
A futási időt a timeit modul timeit függvényével mérjük a három függvény meghívásával egyre növekvő rendezendő elemszámok esetén. A kapott eredmények alapján jól látható, hogy a sorted() függvény használatával nem jelentősen, de mégis kicsit hosszabb futási idő adódik mint, amikor az iterálható objektum elemeit listába helyezzük és e listát rendezzük helyben a sort() metódussal. Ha azonban a rendezendő adatok eleve egy listában állnak elő és ezt rendezzük helyben, akkor nagyon jelentős futási idő csökkenést érhetünk el a sorted() alkalmazásához képest.
Ez, valamint a kevesebb memóriaigény az oka annak, hogy az előző „Nagyméretű adathalmazok rendezése” című bejegyzésben a rendezni kívánt fájlból beolvasott, meghatározott hosszúságú szakaszokat (chunk_list) a sort() metódussal helyben rendezzük, mert a beolvasott adatok rögtön egy listában állnak elő és e lista eredeti elemsorrendjére később nincs szükség.
A Python tudásépítés lépésről lépésre című e-könyvben a sorted() függvény ismertetése a „Beépített függvények” fejezetben található. A lista sort() metódusáról a „Beépített típusok nyilvános metódusai” fejezetben van szó. A timeit modulról és a timeit függvény használatáról pedig részletesen a „Készétel fogyasztás – a szabványos könyvtár moduljainak használata” fejezet „A programvégrehajtás felfüggesztése és a futási idő mérése” alfejezetben lehet olvasni.