Документация по Python

Сортировка по убыванию и возрастанию

В: Документация по Python

Получение минимума или максимума нескольких значений

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

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

Использование ключевого аргумента

Нахождение минимума / максимума последовательности последовательностей возможно:

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

но если вы хотите отсортировать по определенному элементу в каждой последовательности с помощью key -argument:

min(list_of_tuples, key=lambda x: x[0])         # Сортировка по первому элементу
# Output: (0, 10)

min(list_of_tuples, key=lambda x: x[1])         # Сортировка по второму элементу
# Output: (2, 8)

sorted(list_of_tuples, key=lambda x: x[0])      # Сортировка по первому элементу по возрастанию
# Output: [(0, 10), (1, 15), (2, 8)]

sorted(list_of_tuples, key=lambda x: x[1])      # Сортивровка по второму элементу по возрастанию
# Output: [(2, 8), (0, 10), (1, 15)]

import operator   
# Оператор module содержит коэффициенты альтернативные лямбда функции
max(list_of_tuples, key=operator.itemgetter(0)) # Сортировка по первому элементу
# Output: (2, 8)

max(list_of_tuples, key=operator.itemgetter(1)) # Сортировка по второму элементу 
# 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)]

Аргумент по умолчанию для max, min

Вы не можете передать пустую последовательность в max или min :

min([])

 

ValueError: min () arg - пустая последовательность

Однако, с Python 3, вы можете передать в аргументе ключевого слова по default со значением , которое будет возвращено , если последовательность пуста, а не поднимать исключение:

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

 

Особый случай: словари

Получение минимального или максимального или с использованием sorted зависит от итераций над объектом. В случае dict , итерация только по клавишам:

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

Чтобы сохранить словарную структуру, вы должны перебрать .items() :

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

 

Для sorted , можно создать OrderedDict сохранить сортировку, имея dict -like структуру:

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

 

По значению

Опять же, это возможно с помощью key аргумента:

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

Получение отсортированной последовательности

Используя одну последовательность:

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

 

Результат всегда новый list ; исходные данные остаются без изменений.

Минимум и максимум последовательности

Получение минимума последовательности (Iterable) является эквивалентом доступа к первому элементу в sorted последовательностях:

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

 

Максимум является немного более сложной, потому что sorted сохраняет порядок и max возвращает первое значение встречается. В случае отсутствия дубликатов максимум совпадает с последним элементом отсортированного возврата:

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

 

Но нет, если есть несколько элементов, которые оцениваются как имеющие максимальное значение:

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

 

Любая итерация , содержащие элементы , которые поддерживают < или > операции разрешены.

Сделать пользовательские классы заказанными

min , max , и sorted все должны объекты быть упорядочиваема. Для того, чтобы быть правильно упорядочиваема, класс должен определить все 6 методов __lt__ , __gt__ , __ge__ , __le__ , __ne__ и __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

 

Хотя осуществление всех этих методов может показаться ненужным, опуская некоторые из них сделает ваш код склонной к ошибкам .

Примеры:

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 с reverse=True , также использует __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 можно использовать __gt__ вместо этого , если по умолчанию не выполняется:

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)

Сортировка методов поднимет TypeError , если ни __lt__ , ни __gt__ реализованы:

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

res = min(alist) 

Ошибка типа: неупорядоченные типы: IntegerContainer () <IntegerContainer ()

functools.total_ordering декоратор может использоваться упрощая возможность написания этих богатых методы сравнения. Если вы украшаете свой класс с total_ordering , вам нужно реализовать __eq__ , __ne__ и только один из __lt__ , __le__ , __ge__ или __gt__ и декоратор заполнит в остальном:

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


Обратите внимание на то, как > (больше) Теперь заканчивается вызовом меньше , чем метод, а в некоторых случаях даже __eq__ метод. Это также означает, что, если скорость имеет большое значение, вы должны самостоятельно реализовать каждый метод сравнения.

Извлечение N самых больших или N самых маленьких элементов из итерируемого

Для того, чтобы найти некоторое количество (более одного) из больших или мельчайших значений итератора, вы можете использовать nlargest и nsmallest из heapq модуля:

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]

 

Это гораздо эффективнее, чем сортировка всего итерируемого и затем нарезка с конца или начала. Внутри эти функции используют бинарные кучи приоритетной очереди структуру данных, которая является очень эффективной для этого случая использования.

Как min , max и sorted , эти функции принимают дополнительный key ключевого слова аргумента, который должен быть функцией , которая, учитывая элемент, возвращает ключ сортировки.

Вот программа, которая извлекает 1000 самых длинных строк из файла:

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

 

Здесь мы открываем файл и передать дескриптор файла f в nlargest.Повторение файла дает каждую строку файла как отдельную строку; nlargest затем проходит каждый элемент (или линия) передается функции len , чтобы определить его ключ сортировки. len , учитывая строку, возвращает длину строки в символах.

Это требует только хранилища для списка из 1000 самых больших строк, которые можно сравнить с

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

 

которые должны будут держать весь файл в памяти.

Еще от кодкамп
Замечательно! Вы успешно подписались.
Добро пожаловать обратно! Вы успешно вошли
Вы успешно подписались на кодкамп.
Срок действия вашей ссылки истек.
Ура! Проверьте свою электронную почту на наличие волшебной ссылки для входа.
Успех! Ваша платежная информация обновлена.
Ваша платежная информация не была обновлена.