Python Language
Sortierung, Minimum und Maximum
Suche…
Holen Sie sich das Minimum oder Maximum von mehreren Werten
min(7,2,1,5)
# Output: 1
max(7,2,1,5)
# Output: 7
Verwenden Sie das Schlüsselargument
Das Finden des Minimums / Maximums einer Sequenz von Sequenzen ist möglich:
list_of_tuples = [(0, 10), (1, 15), (2, 8)]
min(list_of_tuples)
# Output: (0, 10)
Wenn Sie jedoch in jeder Sequenz nach einem bestimmten Element sortieren möchten, verwenden Sie das key
-argument:
min(list_of_tuples, key=lambda x: x[0]) # Sorting by first element
# Output: (0, 10)
min(list_of_tuples, key=lambda x: x[1]) # Sorting by second element
# Output: (2, 8)
sorted(list_of_tuples, key=lambda x: x[0]) # Sorting by first element (increasing)
# Output: [(0, 10), (1, 15), (2, 8)]
sorted(list_of_tuples, key=lambda x: x[1]) # Sorting by first element
# Output: [(2, 8), (0, 10), (1, 15)]
import operator
# The operator module contains efficient alternatives to the lambda function
max(list_of_tuples, key=operator.itemgetter(0)) # Sorting by first element
# Output: (2, 8)
max(list_of_tuples, key=operator.itemgetter(1)) # Sorting by second element
# Output: (1, 15)
sorted(list_of_tuples, key=operator.itemgetter(0), reverse=True) # Reversed (decreasing)
# Output: [(2, 8), (1, 15), (0, 10)]
sorted(list_of_tuples, key=operator.itemgetter(1), reverse=True) # Reversed(decreasing)
# Output: [(1, 15), (0, 10), (2, 8)]
Default Argument auf max, min
Sie können keine leere Sequenz in max
oder min
:
min([])
ValueError: min () arg ist eine leere Sequenz
Mit Python 3 können Sie jedoch das Schlüsselwortargument default
mit einem Wert übergeben, der zurückgegeben wird, wenn die Sequenz leer ist, anstatt eine Ausnahme auszulösen:
max([], default=42)
# Output: 42
max([], default=0)
# Output: 0
Sonderfall: Wörterbücher
Das Ermitteln des Minimums oder Maximums oder die Verwendung der sorted
hängt von den Iterationen des Objekts ab. Bei dict
erfolgt die Iteration nur über den Tasten:
adict = {'a': 3, 'b': 5, 'c': 1}
min(adict)
# Output: 'a'
max(adict)
# Output: 'c'
sorted(adict)
# Output: ['a', 'b', 'c']
Um die Wörterbuchstruktur .items()
, müssen Sie die .items()
:
min(adict.items())
# Output: ('a', 3)
max(adict.items())
# Output: ('c', 1)
sorted(adict.items())
# Output: [('a', 3), ('b', 5), ('c', 1)]
Für sorted
, können Sie eine erstellen OrderedDict
die Sortierung zu halten , während eine mit dict
-ähnlichen Struktur:
from collections import OrderedDict
OrderedDict(sorted(adict.items()))
# Output: OrderedDict([('a', 3), ('b', 5), ('c', 1)])
res = OrderedDict(sorted(adict.items()))
res['a']
# Output: 3
Nach Wert
Dies ist wiederum mit dem key
möglich:
min(adict.items(), key=lambda x: x[1])
# Output: ('c', 1)
max(adict.items(), key=operator.itemgetter(1))
# Output: ('b', 5)
sorted(adict.items(), key=operator.itemgetter(1), reverse=True)
# Output: [('b', 5), ('a', 3), ('c', 1)]
Eine sortierte Reihenfolge erhalten
Verwendung einer Sequenz:
sorted((7, 2, 1, 5)) # tuple
# Output: [1, 2, 5, 7]
sorted(['c', 'A', 'b']) # list
# Output: ['A', 'b', 'c']
sorted({11, 8, 1}) # set
# Output: [1, 8, 11]
sorted({'11': 5, '3': 2, '10': 15}) # dict
# Output: ['10', '11', '3'] # only iterates over the keys
sorted('bdca') # string
# Output: ['a','b','c','d']
Das Ergebnis ist immer eine neue list
. Die ursprünglichen Daten bleiben unverändert.
Minimum und Maximum einer Sequenz
Das Minimum einer Sequenz (iterierbar) zu erhalten, entspricht dem Zugriff auf das erste Element einer sorted
Sequenz:
min([2, 7, 5])
# Output: 2
sorted([2, 7, 5])[0]
# Output: 2
Das Maximum ist etwas komplizierter, weil sorted
die Reihenfolge hält und max
den zuerst gefundenen Wert zurückgibt. Falls keine Duplikate vorhanden sind, entspricht das Maximum dem letzten Element der sortierten Rückgabe:
max([2, 7, 5])
# Output: 7
sorted([2, 7, 5])[-1]
# Output: 7
Nicht jedoch, wenn mehrere Elemente mit dem Maximalwert bewertet werden:
class MyClass(object):
def __init__(self, value, name):
self.value = value
self.name = name
def __lt__(self, other):
return self.value < other.value
def __repr__(self):
return str(self.name)
sorted([MyClass(4, 'first'), MyClass(1, 'second'), MyClass(4, 'third')])
# Output: [second, first, third]
max([MyClass(4, 'first'), MyClass(1, 'second'), MyClass(4, 'third')])
# Output: first
Jede Iteration, die Elemente enthält, die <
oder >
Operationen unterstützen, ist zulässig.
Machen Sie benutzerdefinierte Klassen bestellbar
min
, max
und sorted
alle Objekte bestellbar sein. Um korrekt bestellbar zu sein, muss die Klasse alle 6 Methoden __lt__
, __gt__
, __ge__
, __le__
, __ne__
und __eq__
:
class IntegerContainer(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.value)
def __lt__(self, other):
print('{!r} - Test less than {!r}'.format(self, other))
return self.value < other.value
def __le__(self, other):
print('{!r} - Test less than or equal to {!r}'.format(self, other))
return self.value <= other.value
def __gt__(self, other):
print('{!r} - Test greater than {!r}'.format(self, other))
return self.value > other.value
def __ge__(self, other):
print('{!r} - Test greater than or equal to {!r}'.format(self, other))
return self.value >= other.value
def __eq__(self, other):
print('{!r} - Test equal to {!r}'.format(self, other))
return self.value == other.value
def __ne__(self, other):
print('{!r} - Test not equal to {!r}'.format(self, other))
return self.value != other.value
Die Implementierung all dieser Methoden erscheint zwar unnötig, aber einige davon wegzulassen, führt dazu, dass Ihr Code anfällig für Fehler wird .
Beispiele:
alist = [IntegerContainer(5), IntegerContainer(3),
IntegerContainer(10), IntegerContainer(7)
]
res = max(alist)
# Out: IntegerContainer(3) - Test greater than IntegerContainer(5)
# IntegerContainer(10) - Test greater than IntegerContainer(5)
# IntegerContainer(7) - Test greater than IntegerContainer(10)
print(res)
# Out: IntegerContainer(10)
res = min(alist)
# Out: IntegerContainer(3) - Test less than IntegerContainer(5)
# IntegerContainer(10) - Test less than IntegerContainer(3)
# IntegerContainer(7) - Test less than IntegerContainer(3)
print(res)
# Out: IntegerContainer(3)
res = sorted(alist)
# Out: IntegerContainer(3) - Test less than IntegerContainer(5)
# IntegerContainer(10) - Test less than IntegerContainer(3)
# IntegerContainer(10) - Test less than IntegerContainer(5)
# IntegerContainer(7) - Test less than IntegerContainer(5)
# IntegerContainer(7) - Test less than IntegerContainer(10)
print(res)
# Out: [IntegerContainer(3), IntegerContainer(5), IntegerContainer(7), IntegerContainer(10)]
mit reverse=True
sorted
reverse=True
verwendet auch __lt__
:
res = sorted(alist, reverse=True)
# Out: IntegerContainer(10) - Test less than IntegerContainer(7)
# IntegerContainer(3) - Test less than IntegerContainer(10)
# IntegerContainer(3) - Test less than IntegerContainer(10)
# IntegerContainer(3) - Test less than IntegerContainer(7)
# IntegerContainer(5) - Test less than IntegerContainer(7)
# IntegerContainer(5) - Test less than IntegerContainer(3)
print(res)
# Out: [IntegerContainer(10), IntegerContainer(7), IntegerContainer(5), IntegerContainer(3)]
sorted
kann __gt__
stattdessen __gt__
verwenden, wenn der Standard nicht implementiert ist:
del IntegerContainer.__lt__ # The IntegerContainer no longer implements "less than"
res = min(alist)
# Out: IntegerContainer(5) - Test greater than IntegerContainer(3)
# IntegerContainer(3) - Test greater than IntegerContainer(10)
# IntegerContainer(3) - Test greater than IntegerContainer(7)
print(res)
# Out: IntegerContainer(3)
Sortiermethoden TypeError
einen TypeError
wenn weder __lt__
noch __gt__
implementiert sind:
del IntegerContainer.__gt__ # The IntegerContainer no longer implements "greater then"
res = min(alist)
TypeError: nicht anordnungsfähige Typen: IntegerContainer () <IntegerContainer ()
functools.total_ordering
Dekorator functools.total_ordering
kann verwendet werden, um die Erstellung dieser umfangreichen Vergleichsmethoden zu vereinfachen. Wenn Sie Ihre Klasse mit total_ordering
, müssen Sie __eq__
, __ne__
und nur eines von __lt__
, __le__
, __ge__
oder __gt__
. Der Dekorateur füllt den Rest aus:
import functools
@functools.total_ordering
class IntegerContainer(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return "{}({})".format(self.__class__.__name__, self.value)
def __lt__(self, other):
print('{!r} - Test less than {!r}'.format(self, other))
return self.value < other.value
def __eq__(self, other):
print('{!r} - Test equal to {!r}'.format(self, other))
return self.value == other.value
def __ne__(self, other):
print('{!r} - Test not equal to {!r}'.format(self, other))
return self.value != other.value
IntegerContainer(5) > IntegerContainer(6)
# Output: IntegerContainer(5) - Test less than IntegerContainer(6)
# Returns: False
IntegerContainer(6) > IntegerContainer(5)
# Output: IntegerContainer(6) - Test less than IntegerContainer(5)
# Output: IntegerContainer(6) - Test equal to IntegerContainer(5)
# Returns True
Beachten Sie, wie die >
( größer als ) jetzt die Methode less als und in einigen Fällen sogar die Methode __eq__
. Das bedeutet auch, dass, wenn Geschwindigkeit von großer Bedeutung ist, Sie jede ausführliche Vergleichsmethode selbst implementieren sollten.
Extrahieren von N größten oder N kleinsten Elementen aus einer iterierbaren
Um eine bestimmte Anzahl (mehr als einen) der größten oder kleinsten Werte einer Iteration zu finden, können Sie die nlargest
und nsmallest
des heapq
Moduls verwenden:
import heapq
# get 5 largest items from the range
heapq.nlargest(5, range(10))
# Output: [9, 8, 7, 6, 5]
heapq.nsmallest(5, range(10))
# Output: [0, 1, 2, 3, 4]
Dies ist viel effizienter, als das gesamte Iterable zu sortieren und dann am Ende oder Anfang zu schneiden. Intern verwenden diese Funktionen die Datenstruktur der binären Heap- Prioritätswarteschlange , die für diesen Anwendungsfall sehr effizient ist.
Wie min
, max
und sorted
akzeptieren diese Funktionen das optionale key
, das eine Funktion sein muss, die bei einem Element seinen Sortierschlüssel zurückgibt.
Hier ist ein Programm, das 1000 längste Zeilen aus einer Datei extrahiert:
import heapq
with open(filename) as f:
longest_lines = heapq.nlargest(1000, f, key=len)
Hier öffnen wir die Datei und übergeben das nlargest
f
an nlargest
. Durch die Iteration der Datei wird jede Zeile der Datei als separate Zeichenfolge angezeigt. nlargest
dann jedes Element (oder jede Zeile) an die Funktion len
, um den Sortierschlüssel zu bestimmen. len
Angabe einer Zeichenfolge gibt len
die Länge der Zeile in Zeichen zurück.
Dies erfordert nur Speicherplatz für eine Liste von 1000 größten Zeilen, die mit denen verglichen werden können
longest_lines = sorted(f, key=len)[1000:]
die muss die gesamte Datei im Speicher halten .