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

Введение

Примеры

  • 1

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

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

     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])         # 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)]
  • 1

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

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

     min([])
    
     

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

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

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

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

    Получение минимального или максимального или с использованием 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)] 
  • 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 ; исходные данные остаются без изменений.

  • 0

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

    Получение минимума последовательности (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
    
     

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

  • 7

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

    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__ метод. Это также означает, что, если скорость имеет большое значение, вы должны самостоятельно реализовать каждый метод сравнения.

  • 1

    Извлечение 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:]
    
     

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

Синтаксис

Параметры

Примечания