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 .



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow