Szukaj…


Uzyskiwanie minimum lub maksimum kilku wartości

min(7,2,1,5)
# Output: 1

max(7,2,1,5)
# Output: 7

Za pomocą kluczowego argumentu

Możliwe jest znalezienie minimum / maksimum sekwencji sekwencji:

list_of_tuples = [(0, 10), (1, 15), (2, 8)]
min(list_of_tuples)
# Output: (0, 10)

ale jeśli chcesz sortować według określonego elementu w każdej sekwencji, użyj 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)]

Domyślny argument do maksimum, min

Nie możesz przekazać pustej sekwencji na max lub min :

min([])

ValueError: min () arg jest pustą sekwencją

Jednak w Pythonie 3 możesz przekazać argument słowa kluczowego default z wartością, która zostanie zwrócona, jeśli sekwencja jest pusta, zamiast zgłaszania wyjątku:

max([], default=42)        
# Output: 42
max([], default=0)        
# Output: 0

Przypadek szczególny: słowniki

Uzyskanie minimum lub maksimum lub użycie sorted zależy od iteracji obiektu. W przypadku dict iteracja dotyczy tylko klawiszy:

adict = {'a': 3, 'b': 5, 'c': 1}
min(adict)
# Output: 'a'
max(adict)
# Output: 'c'
sorted(adict)
# Output: ['a', 'b', 'c']

Aby zachować strukturę słownika, musisz iterować po .items() :

min(adict.items())
# Output: ('a', 3)
max(adict.items())
# Output: ('c', 1)
sorted(adict.items())
# Output: [('a', 3), ('b', 5), ('c', 1)]

Aby sorted , możesz utworzyć OrderedDict aby zachować sortowanie, mając strukturę podobną do dict :

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

Według wartości

Ponownie jest to możliwe przy użyciu key argumentu:

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)]

Uzyskiwanie uporządkowanej sekwencji

Używając jednej sekwencji:

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']

Rezultatem jest zawsze nowa list ; oryginalne dane pozostają niezmienione.

Minimum i maksimum sekwencji

Uzyskanie minimum sekwencji (iterowalnej) jest równoznaczne z dostępem do pierwszego elementu sorted sekwencji:

min([2, 7, 5])
# Output: 2
sorted([2, 7, 5])[0]
# Output: 2

Wartość maksymalna jest nieco bardziej skomplikowana, ponieważ sorted utrzymuje porządek, a max zwraca pierwszą napotkaną wartość. W przypadku braku duplikatów maksimum jest takie samo jak ostatni element posortowanego zwrotu:

max([2, 7, 5])
# Output: 7
sorted([2, 7, 5])[-1]
# Output: 7

Ale nie, jeśli istnieje wiele elementów, które są oceniane jako posiadające maksymalną wartość:

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

Dozwolone są wszelkie iterowalne elementy zawierające operacje < lub > .

Spraw, by klasy niestandardowe były uporządkowane

min , max i sorted wszystkie obiekty muszą być uporządkowane. Aby poprawnie zamówić, klasa musi zdefiniować wszystkie 6 metod __lt__ , __gt__ , __ge__ , __le__ , __ne__ i __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

Chociaż wdrożenie wszystkich tych metod wydaje się niepotrzebne, pominięcie niektórych z nich spowoduje, że Twój kod będzie podatny na błędy .

Przykłady:

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 pomocą reverse=True używa również __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)]

Ale sorted może zamiast tego użyć __gt__ jeśli domyślna nie jest zaimplementowana:

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)

Sortowanie metody podniesie TypeError jeśli nie __lt__ ani __gt__ realizowane są:

del IntegerContainer.__gt__   # The IntegerContainer no longer implements "greater then"

res = min(alist) 

TypeError: unorderable types: IntegerContainer () <IntegerContainer ()


można użyć functools.total_ordering upraszcza pisanie tych bogatych metod porównywania. Jeśli udekorujesz swoją klasę total_ordering , musisz zaimplementować __eq__ , __ne__ i tylko jeden z __lt__ , __le__ , __ge__ lub __gt__ , a dekorator wypełni resztę:

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

Zauważ, że > ( większe niż ) teraz wywołuje metodę mniej niż , aw niektórych przypadkach nawet metodę __eq__ . Oznacza to również, że jeśli szybkość ma ogromne znaczenie, należy samodzielnie wdrożyć każdą metodę porównywania bogatego.

Wydobywanie N największych lub N najmniejszych przedmiotów z iterowalnego

Aby znaleźć numer (więcej niż jeden) największych lub najmniejszych wartościach iterable można użyć nlargest i nsmallest z heapq module:

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]

Jest to o wiele bardziej wydajne niż sortowanie całego iterowalnego, a następnie krojenie od końca lub od początku. Wewnętrznie te funkcje używają struktury danych kolejki binarnej priorytetów sterty , co jest bardzo wydajne w tym przypadku użycia.

Jak min , max i sorted , funkcje te akceptują opcjonalnego key argumentu słowa kluczowego, które muszą być funkcja, która, biorąc pod uwagę element, zwraca swój klucz sortowania.

Oto program, który wyodrębnia 1000 najdłuższych linii z pliku:

import heapq
with open(filename) as f:
    longest_lines = heapq.nlargest(1000, f, key=len)

Tutaj otwieramy plik i przekazujemy uchwyt pliku f do nlargest . Iteracja pliku daje każdy wiersz pliku jako osobny ciąg; nlargest następnie przekazuje każdy element (lub linię) jest przekazywany do funkcji len celu ustalenia jej klucza sortowania. len , podany ciąg, zwraca długość wiersza w znakach.

To wymaga jedynie miejsca na listę 1000 największych linii, z którymi można się przeciwstawić

longest_lines = sorted(f, key=len)[1000:]

który będzie musiał przechowywać cały plik w pamięci .



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow