Python Language
Sorteren, minimum en maximum
Zoeken…
Het minimum of maximum van meerdere waarden verkrijgen
min(7,2,1,5)
# Output: 1
max(7,2,1,5)
# Output: 7
Het belangrijkste argument gebruiken
Het minimum / maximum van een reeks reeksen vinden is mogelijk:
list_of_tuples = [(0, 10), (1, 15), (2, 8)]
min(list_of_tuples)
# Output: (0, 10)
maar als u op een specifiek element in elke reeks wilt sorteren, gebruikt u het key
:
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)]
Standaard argument naar max, min
Je kunt een lege reeks niet in max
of min
doorgeven:
min([])
ValueError: min () arg is een lege reeks
Met Python 3 kunt u echter het default
het sleutelwoordargument doorgeven met een waarde die wordt geretourneerd als de reeks leeg is, in plaats van een uitzondering te genereren:
max([], default=42)
# Output: 42
max([], default=0)
# Output: 0
Speciaal geval: woordenboeken
Het minimum of maximum krijgen of sorted
afhankelijk van iteraties over het object. In het geval van dict
is de iteratie alleen over de toetsen:
adict = {'a': 3, 'b': 5, 'c': 1}
min(adict)
# Output: 'a'
max(adict)
# Output: 'c'
sorted(adict)
# Output: ['a', 'b', 'c']
Om de woordenboekstructuur te behouden, moet u de .items()
herhalen:
min(adict.items())
# Output: ('a', 3)
max(adict.items())
# Output: ('c', 1)
sorted(adict.items())
# Output: [('a', 3), ('b', 5), ('c', 1)]
Voor sorted
kun je een OrderedDict
om het sorteren te behouden terwijl je een dict
achtige structuur hebt:
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
Op waarde
Ook dit is mogelijk met behulp van het key
argument:
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)]
Een gesorteerde volgorde krijgen
Eén reeks gebruiken:
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']
Het resultaat is altijd een nieuwe list
; de oorspronkelijke gegevens blijven ongewijzigd.
Minimum en maximum van een reeks
Het minimum van een reeks (iterabel) verkrijgen is hetzelfde als toegang krijgen tot het eerste element van een sorted
reeks:
min([2, 7, 5])
# Output: 2
sorted([2, 7, 5])[0]
# Output: 2
Het maximum is iets gecompliceerder, omdat sorted
de volgorde behoudt en max
de eerste waarde retourneert. In het geval er geen duplicaten zijn, is het maximum hetzelfde als het laatste element van de gesorteerde retour:
max([2, 7, 5])
# Output: 7
sorted([2, 7, 5])[-1]
# Output: 7
Maar niet als er meerdere elementen zijn waarvan wordt geëvalueerd dat ze de maximale waarde hebben:
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
Elke iterabele die elementen bevat die <
of >
bewerkingen ondersteunen, is toegestaan.
Maak aangepaste klassen bestelbaar
min
, max
en sorted
moeten alle objecten geordend worden. Om correct te kunnen bestellen, moet de klasse alle 6 methoden __lt__
, __gt__
, __ge__
, __le__
, __ne__
en __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
Hoewel het implementeren van al deze methoden overbodig lijkt, zal het weglaten van enkele van deze methoden je code gevoelig maken voor fouten .
Voorbeelden:
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)]
sorted
met reverse=True
gebruikt ook __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)]
Maar sorted
kan in plaats daarvan __gt__
gebruiken als de standaard niet is geïmplementeerd:
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)
Sorteermethoden zullen een TypeError
als noch __lt__
noch __gt__
zijn geïmplementeerd:
del IntegerContainer.__gt__ # The IntegerContainer no longer implements "greater then"
res = min(alist)
TypeError: unorderable types: IntegerContainer () <IntegerContainer ()
functools.total_ordering
decorator kan worden gebruikt om het schrijven van deze rijke vergelijkingsmethoden te vereenvoudigen. Als je je klas decoreert met total_ordering
, moet je __eq__
, __ne__
en slechts een van de __lt__
, __le__
, __ge__
of __gt__
, en de decorateur vult de rest in:
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
Merk op dat de >
( groter dan ) nu de methode less dan aanroept en in sommige gevallen zelfs de methode __eq__
. Dit betekent ook dat als snelheid van groot belang is, u elke rijke vergelijkingsmethode zelf moet implementeren.
N grootste of N kleinste items extraheren uit een iterabel
Om een aantal (meer dan één) van de grootste of kleinste waarden van een iterabel te vinden, kunt u de nlargest
en nsmallest
van de heapq
module gebruiken:
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]
Dit is veel efficiënter dan het hele iterabele sorteren en vervolgens vanaf het einde of begin snijden. Intern gebruiken deze functies de binaire heap prioriteit wachtrij datastructuur, die zeer efficiënt is voor deze use case.
Net als min
, max
en sorted
, accepteren deze functies het optionele key
sleutelwoord, dat een functie moet zijn die, gegeven een element, de sorteersleutel retourneert.
Hier is een programma dat 1000 langste regels uit een bestand haalt:
import heapq
with open(filename) as f:
longest_lines = heapq.nlargest(1000, f, key=len)
Hier openen we het bestand en geven de bestandsingang f
aan nlargest
. Als u het bestand herhaalt, krijgt elke regel van het bestand een afzonderlijke tekenreeks; nlargest
geeft vervolgens elk element (of regel) door aan de functie len
om de sorteersleutel te bepalen. len
, gegeven een string, geeft de lengte van de regel terug in tekens.
Dit heeft alleen opslag nodig voor een lijst met 1000 grootste lijnen tot nu toe, waarmee kan worden gecontrasteerd
longest_lines = sorted(f, key=len)[1000:]
die het hele bestand in het geheugen moet houden .