Как найти порядок числа python

Предупреждение: правильный ответ уже дан. То что написано тут — упражнение для ума.

Что такое показатель степени после E? Это не такая простая вещь. Формат {:e} выводит число в научном формате:

@>>> '{:e}'.format(9.999999)
'9.999999e+00'
@>>> '{:e}'.format(9.9999999)
'1.000000e+01'

Первая проблема: числа выводятся округлёнными до шести знаков после запятой. Поправить можно подняв точность до 17 знаков. Считается что столько знаков хранится в числе. «Считается» вставлено так как это приближённая оценка.

@>>> '{:.17e}'.format(9.9999999)
'9.99999990000000061e+00'

Так лучше.

Показатель степени примерно равен целой части десятичного логарифма числа: int(math.log10(x)). В этой таблице вычислены диапазоны в которых целая часть десятичного логарифма постоянна:

int(math.log10([1.00000000000000019e-01, 9.99999999999999822e+00])) ==  0
int(math.log10([1.00000000000000000e+01, 9.99999999999999716e+01])) ==  1
int(math.log10([9.99999999999999858e+01, 9.99999999999999318e+02])) ==  2
int(math.log10([9.99999999999999432e+02, 9.99999999999999454e+03])) ==  3
int(math.log10([9.99999999999999636e+03, 9.99999999999998981e+04])) ==  4
int(math.log10([9.99999999999999127e+04, 9.99999999999998836e+05])) ==  5
int(math.log10([9.99999999999998952e+05, 9.99999999999998882e+06])) ==  6
int(math.log10([9.99999999999999069e+06, 9.99999999999998957e+07])) ==  7
int(math.log10([9.99999999999999106e+07, 9.99999999999997735e+08])) ==  8
int(math.log10([9.99999999999997854e+08, 9.99999999999997902e+09])) ==  9
int(math.log10([9.99999999999998093e+09, 9.99999999999997864e+10])) == 10
...
int(math.log10([9.99999999999983758e+97, 9.99999999999983576e+98])) == 98
int(math.log10([9.99999999999983697e+98, 9.99999999999983503e+99])) == 99

Видно что логарифм слегка занижает результат в большей части случаев. Точность весьма высока (14 знаков) но не идеальна.

Для сравнения таблица когда показатель вычисляется прямой печатью числа:

def ilog10(x):
    s = '{:.17e}'.format(x)
    m = re.search('e(.*)', s)
    return int(m.group(1))
ilog10([1.00000000000000000e+00, 9.99999999999999822e+00]) ==  0
ilog10([1.00000000000000000e+01, 9.99999999999999858e+01]) ==  1
ilog10([1.00000000000000000e+02, 9.99999999999999886e+02]) ==  2
ilog10([1.00000000000000000e+03, 9.99999999999999818e+03]) ==  3
ilog10([1.00000000000000000e+04, 9.99999999999999854e+04]) ==  4
ilog10([1.00000000000000000e+05, 9.99999999999999884e+05]) ==  5
ilog10([1.00000000000000000e+06, 9.99999999999999814e+06]) ==  6
ilog10([1.00000000000000000e+07, 9.99999999999999851e+07]) ==  7
ilog10([1.00000000000000000e+08, 9.99999999999999881e+08]) ==  8
ilog10([1.00000000000000000e+09, 9.99999999999999809e+09]) ==  9
ilog10([1.00000000000000000e+10, 9.99999999999999847e+10]) == 10
...
ilog10([1.00000000000000000e+21, 9.99999999999999790e+21]) == 21
ilog10([1.00000000000000000e+22, 9.99999999999999916e+22]) == 22
ilog10([1.00000000000000008e+23, 9.99999999999999983e+23]) == 23
ilog10([1.00000000000000012e+24, 9.99999999999999876e+24]) == 24
...
ilog10([1.00000000000000015e+98, 9.99999999999999967e+98]) == 98
ilog10([1.00000000000000009e+99, 9.99999999999999822e+99]) == 99

Тут точнее. Нижние границы точные до 22. Выше 10^22 степени десятки не представляются точно в вещественном формате.

Показатель определяется точнее с помощью печати числа и последующего чтения из строки. Ситуация странная и, кажется, её просто так не исправить. Стандарт даёт гарантии точности при печати чисел, которые выше точностей при вычислении логарифмов. Тут речь не про стандарт Python, а про стандарт C и IEEE 754.

Но не смотря на это, всегда считайте показатель логарифмом.

Ниже код, который составляет таблицы:

import math
import re


def binary_search(low, high, p):
    assert low < high
    assert not p(low)
    assert p(high)
    while True:
        middle = low + (high - low) / 2
        assert low <= middle <= high
        if middle == low or middle == high:
            return low, high
        if p(middle):
            high = middle
        else:
            low = middle


def ilog10_p(x, p):
    fmt = '{{:.{}e}}'.format(p)
    s = fmt.format(x)
    m = re.search('e(.*)', s)
    return int(m.group(1))


def ilog10(x):
    assert ilog10_p(x, 17) == ilog10_p(x, 34)
    return ilog10_p(x, 17)


def test(prefix, suffix, f):
    for e in range(0, 100):
        _, low = binary_search(1e-1, 1e101, lambda x: f(x) >= e)
        high, _ = binary_search(1e-1, 1e101, lambda x: f(x) > e)
        assert f(low) == e
        assert f(high) == e
        print('{}[{:.17e}, {:.17e}]{} == {:2}'.format(prefix, low, high, suffix, e))


test('int(math.log10(', '))', lambda x: int(math.log10(x)))
test('ilog10(', ')', ilog10)

>>> x = [4,5,81,5,28958,28] # first list
>>> print sorted(x)
[4, 5, 5, 28, 81, 28958]
>>> x
[4, 5, 81, 5, 28958, 28]
>>> x.sort() # sort the list in place
>>> x
[4, 5, 5, 28, 81, 28958]
>>> x.append(1) # add to the list
>>> x
[4, 5, 5, 28, 81, 28958, 1]
>>> sorted(x)
[1, 4, 5, 5, 28, 81, 28958]

As many others have pointed out, you can sort a number forwards like:

>>> int(''.join(sorted(str(2314))))
1234

That’s pretty much the most standard way.

Reverse a number? Doesn’t work well in a number with trailing zeros.

>>> y = int(''.join(sorted(str(2314))))
>>> y
1234
>>> int(str(y)[::-1])
4321

The [::-1] notation indicates that the iterable is to be traversed in reverse order.

Все программисты должны будут написать код для сортировки элементов или данных в какой-то момент. Сортировка может иметь решающее значение для взаимодействия с пользователем в вашем приложении, будь то упорядочение самой последней активности пользователя по отметке времени или размещение списка получателей электронной почты в алфавитном порядке по фамилии. Функциональность сортировки Python предлагает надежные функции для базовой сортировки или настройки порядка на детальном уровне.

В этом руководстве вы узнаете, как сортировать различные типы данных в разных структурах данных, настраивать порядок и работать с двумя различными методами сортировки в Python.

К концу этого руководства вы будете знать, как:

  • Реализовать базовую сортировку и упорядочение Python для структур данных

  • Различия междуsorted() и.sort()

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

Для этого урока вам потребуются базовые знания какlists and tuples, так иsets. Эти структуры данных будут использоваться в этом руководстве, и с ними будут выполняться некоторые основные операции. Кроме того, в этом руководстве используется Python 3, поэтому пример вывода в этом руководстве может немного отличаться, если вы используете Python 2.

Значения для заказа сsorted()

Чтобы начать сортировку с помощью Python, вы сначала узнаете, как сортировать как числовые, так и строковые данные.

Сортировка чисел

Вы можете использовать Python для сортировки списка с помощьюsorted(). В этом примере определяется список целых чисел, а затем вызываетсяsorted() с переменнойnumbers в качестве аргумента:

>>>

>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers)
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]

Вывод этого кода — новый отсортированный список. Когда печатается исходная переменная, начальные значения не изменяются.

В этом примере показаны четыре важные характеристикиsorted():

  1. Функциюsorted() определять не нужно. Это встроенная функция, которая доступна в стандартной установке Python.

  2. sorted(), без дополнительных аргументов или параметров, упорядочивает значения вnumbers в порядке возрастания, то есть от наименьшего к наибольшему.

  3. Исходная переменнаяnumbers не изменяется, потому чтоsorted() обеспечивает отсортированный вывод и не меняет исходное значение на месте.

  4. Когда вызываетсяsorted(), он предоставляет упорядоченный список в качестве возвращаемого значения.

Этот последний пункт означает, чтоsorted() можно использовать в списке, а результат можно сразу присвоить переменной:

>>>

>>> numbers = [6, 9, 3, 1]
>>> numbers_sorted = sorted(numbers)
>>> numbers_sorted
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]

В этом примере теперь есть новая переменнаяnumbers_sorted, в которой хранится выводsorted().

Вы можете подтвердить все эти наблюдения, вызвавhelp() наsorted(). Необязательные аргументыkey иreverse будут рассмотрены позже в руководстве:

>>>

>>> # Python 3
>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.

Technical Detail: Если вы переходите с Python 2 и знакомы с его одноименной функцией, вы должны знать о нескольких важных изменениях в Python 3:

  1. sorted() в Python 3 не имеет параметраcmp. Вместо этого для введения настраиваемой логики сортировки используется толькоkey.

  2. key иreverse должны передаваться как аргументы ключевого слова, в отличие от Python 2, где они могут передаваться как позиционные аргументы.

Если вам нужно преобразовать функцию Python 2cmp в функциюkey, попробуйтеfunctools.cmp_to_key(). Этот урок не будет охватывать какие-либо примеры использования Python 2.

sorted() можно использовать для кортежей и наборов очень похоже:

>>>

>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]

Обратите внимание на то, что, хотя входом был набор и кортеж, выходом является список, потому чтоsorted() по определению возвращает новый список. Возвращенный объект может быть приведен к новому типу, если он должен соответствовать типу ввода. Будьте осторожны при попытке привести результирующий список обратно к набору, так как набор по определению неупорядочен:

>>>

>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]
>>> tuple(numbers_tuple_sorted)
(1, 3, 6, 9)
>>> set(numbers_set_sorted)
{0, 1, 10, 5}

Значениеnumbers_set_sorted при приведении кset не упорядочивается, как ожидалось. Другая переменная,numbers_tuple_sorted, сохранила отсортированный порядок.

Сортировка строк

Типыstr сортируются аналогично другим итерациям, таким как список и кортеж. В приведенном ниже примере показано, какsorted() выполняет итерацию по каждому символу в переданном ему значении и упорядочивает их в выводе:

>>>

>>> string_number_value = '34521'
>>> string_value = 'I like to sort'
>>> sorted_string_number = sorted(string_number_value)
>>> sorted_string = sorted(string_value)
>>> sorted_string_number
['1', '2', '3', '4', '5']
>>> sorted_string
[' ', ' ', ' ', 'I', 'e', 'i', 'k', 'l', 'o', 'o', 'r', 's', 't', 't']

sorted() будет рассматриватьstr как список и перебирать каждый элемент. Вstr каждый элемент означает каждый символ вstr. sorted() не будет обрабатывать предложение по-разному, а отсортирует каждый символ, включая пробелы.

.split() может изменить это поведение и очистить вывод, а.join() может собрать все вместе. Мы рассмотрим конкретный порядок вывода и почему это так в ближайшее время:

>>>

>>> string_value = 'I like to sort'
>>> sorted_string = sorted(string_value.split())
>>> sorted_string
['I', 'like', 'sort', 'to']
>>> ' '.join(sorted_string)
'I like sort to'

Исходное предложение в этом примере преобразуется в список слов вместо того, чтобы оставить его какstr. Затем этот список сортируется и объединяется, чтобы снова сформироватьstr вместо списка.

Ограничения и ошибки с сортировкой Python

Стоит отметить некоторые ограничения и странное поведение, которое может возникнуть, когда вы используете Python для сортировки значений помимо целых чисел.

Списки с несовместимыми типами данных не могут бытьsorted()

Существуют типы данных, которые нельзя сравнивать друг с другом, используя толькоsorted(), потому что они слишком разные. Python вернет ошибку, если вы попытаетесь использоватьsorted() в списке, содержащем несопоставимые данные. В этом примереNone иint в одном списке не могут быть отсортированы из-за их несовместимости:

>>>

>>> mixed_types = [None, 0]
>>> sorted(mixed_types)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<' not supported between instances of 'int' and 'NoneType'

Эта ошибка показывает, почему Python не может сортировать значения, данные ему. Он пытается упорядочить значения с помощью оператора «меньше» (<), чтобы определить, какое значение ниже в порядке сортировки. Вы можете повторить эту ошибку, сравнив вручную два значения:

>>>

>>> None < 0
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<' not supported between instances of 'NoneType' and 'int'

Тот жеTypeError выдается, когда вы пытаетесь сравнить два несопоставимых значения без использованияsorted().

Если значения в списке можно сравнить и не выдастTypeError, то список можно отсортировать. Это предотвращает сортировку итераций по внутренне неупорядоченным значениям и создание вывода, который может не иметь смысла.

Например, должно ли число1 стоять перед словомapple? Однако, если итератор содержит комбинацию целых чисел и строк, которые являются числами, они могут быть преобразованы в сопоставимые типы данных с использованием понимания списка:

>>>

>>> mixed_numbers = [5, "1", 100, "34"]
>>> sorted(mixed_numbers)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<' not supported between instances of 'str' and 'int'
>>> # List comprehension to convert all values to integers
>>> [int(x) for x in mixed_numbers]
[5, 1, 100, 34]
>>> sorted([int(x) for x in mixed_numbers])
[1, 5, 34, 100]

Каждый элемент вmixed_numbers имеет вызовint() для преобразования любых значенийstr в значенияint. Затем вызываетсяsorted(), который может успешно сравнивать каждый элемент и предоставлять отсортированный вывод.

Python также может неявно преобразовывать значение в другой тип. В приведенном ниже примере оценка1 <= 0 является ложным утверждением, поэтому результат оценки будетFalse. Число1 может быть преобразовано вTrue как типbool, а0 преобразуется вFalse.

Несмотря на то, что элементы в списке выглядят по-разному, все они могут быть преобразованы в логические значения (True илиFalse) и сравнены друг с другом с помощьюsorted():

>>>

>>> similar_values = [False, 0, 1, 'A' == 'B', 1 <= 0]
>>> sorted(similar_values)
[False, 0, False, False, 1]

'A' == 'B' и1 <= 0 преобразуются вFalse и возвращаются в упорядоченном выводе.

Этот пример иллюстрирует важный аспект сортировки:sort stability. В Python, когда вы сортируете равные значения, они сохранят свой первоначальный порядок в выводе. Несмотря на то, что1 переместился, все остальные значения равны, поэтому они сохраняют свой исходный порядок относительно друг друга. В приведенном ниже примере все значения считаются равными и сохраняют свои исходные позиции:

>>>

>>> false_values = [False, 0, 0, 1 == 2, 0, False, False]
>>> sorted(false_values)
[False, 0, 0, False, 0, False, False]

Если вы проверите исходный порядок и отсортированный вывод, вы увидите, что1 == 2 преобразован вFalse, и весь отсортированный вывод находится в исходном порядке.

Когда вы сортируете строки, дело имеет значение

sorted() можно использовать в списке строк для сортировки значений в порядке возрастания, который по умолчанию отображается в алфавитном порядке:

>>>

>>> names = ['Harry', 'Suzy', 'Al', 'Mark']
>>> sorted(names)
['Al', 'Harry', 'Mark', 'Suzy']

Однако Python используетUnicode Code Point первой буквы в каждой строке для определения порядка сортировки по возрастанию. Это означает, чтоsorted() не будет обрабатывать именаAl иal одинаково. В этом примереord() используется для возврата точки кода Unicode первой буквы в каждой строке:

>>>

>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case)
['Mark', 'Suzy', 'al', 'harry']
>>> # List comprehension for Unicode Code Point of first letter in each word
>>> [(ord(name[0]), name[0]) for name in sorted(names_with_case)]
[(77, 'M'), (83, 'S'), (97, 'a'), (104, 'h')]

name[0] возвращает первый символ в каждом элементеsorted(names_with_case), аord() предоставляет точку кода Unicode. Несмотря на то, чтоa стоит передM в алфавите, кодовая точка дляM стоит передa, поэтому отсортированный вывод имеет сначалаM.

Если первая буква такая же, тоsorted() будет использовать второй символ для определения порядка, а третий символ, если он такой же, и так далее, вплоть до конца строки:

>>>

>>> very_similar_strs = ['hhhhhd', 'hhhhha', 'hhhhhc','hhhhhb']
>>> sorted(very_similar_strs)
['hhhhha', 'hhhhhb', 'hhhhhc', 'hhhhhd']

Все значенияvery_similar_strs идентичны, за исключением последнего символа. sorted() будет сравнивать строки, и, поскольку первые пять символов совпадают, вывод будет основан на шестом символе.

Строки, которые содержат одинаковые значения, будут отсортированы в кратчайшие и самые длинные из-за того, что у более коротких строк нет элементов для сравнения с более длинными строками:

>>>

>>> different_lengths = ['hhhh', 'hh', 'hhhhh','h']
>>> sorted(different_lengths)
['h', 'hh', 'hhhh', 'hhhhh']

Самая короткая строкаh упорядочивается первой, а самая длинная,hhhhh, — последней.

Использованиеsorted() с аргументомreverse

Как показано в документацииhelp() дляsorted(), существует необязательный аргумент ключевого слова с именемreverse, который изменяет поведение сортировки на основе присвоенного ему логического значения. Еслиreverse назначенTrue, то сортировка будет в порядке убывания:

>>>

>>> names = ['Harry', 'Suzy', 'Al', 'Mark']
>>> sorted(names)
['Al', 'Harry', 'Mark', 'Suzy']
>>> sorted(names, reverse=True)
['Suzy', 'Mark', 'Harry', 'Al']

Логика сортировки остается той же, то есть имена сортируются по первой букве. Но результат был отменен с ключевым словомreverse, установленным наTrue.

Когда присвоеноFalse, порядок останется возрастающим. Любой из предыдущих примеров можно использовать, чтобы увидеть поведение обратного, используя какTrue, так иFalse:

>>>

>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case, reverse=True)
['harry', 'al', 'Suzy', 'Mark']
>>> similar_values = [False, 1, 'A' == 'B', 1 <= 0]
>>> sorted(similar_values, reverse=True)
[1, False, False, False]
>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers, reverse=False)
[1, 3, 6, 9]

sorted() с аргументомkey

Одним из самых мощных компонентовsorted() является аргумент ключевого словаkey. Этот аргумент ожидает, что ему будет передана функция, и эта функция будет использоваться для каждого значения в отсортированном списке для определения результирующего порядка.

Чтобы продемонстрировать базовый пример, давайте предположим, что для упорядочения определенного списка необходимо указать длину строк в списке, от самой короткой до самой длинной. Функция для возврата длины строкиlen() будет использоваться с аргументомkey:

>>>

>>> word = 'paper'
>>> len(word)
5
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=len)
['pie', 'book', 'banana', 'Washington']

Результирующий порядок представляет собой список с порядком строк от кратчайшего до самого длинного. Длина каждого элемента в списке определяетсяlen(), а затем возвращается в порядке возрастания.

Вернемся к более раннему примеру сортировки по первой букве, когда дело обстоит иначе. key можно использовать для решения этой проблемы путем преобразования всей строки в нижний регистр:

>>>

>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case)
['Mark', 'Suzy', 'al', 'harry']
>>> sorted(names_with_case, key=str.lower)
['al', 'harry', 'Mark', 'Suzy']

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

Есть два основных ограничения при использовании функций с аргументомkey.

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

В приведенном ниже примере показано определение функции сложения, которая принимает два аргумента. Когда эта функция используется вkey в списке чисел, она терпит неудачу, потому что отсутствует второй аргумент. Каждый раз, когдаadd() вызывается во время сортировки, он получает только один элемент из списка за раз:

>>>

>>> def add(x, y):
...     return x + y
...
>>> values_to_add = [1, 2, 3]
>>> sorted(values_to_add, key=add)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: add() missing 1 required positional argument: 'y'

Второе ограничение заключается в том, что функция, используемая сkey, должна иметь возможность обрабатывать все значения в итерируемом объекте. Например, у вас есть список чисел, представленных в виде строк, которые будут использоваться вsorted(), иkey попытается преобразовать их в числа с помощьюint. Если значение в итерируемом не может быть преобразовано в целое число, то функция завершится ошибкой:

>>>

>>> values_to_cast = ['1', '2', '3', 'four']
>>> sorted(values_to_cast, key=int)
Traceback (most recent call last):
  File "", line 1, in 
ValueError: invalid literal for int() with base 10: 'four'

Каждое числовое значение какstr может быть преобразовано вint, аfour — нет. Это вызывает увеличениеValueError и объясняет, чтоfour не может быть преобразован вint, потому что он недействителен.

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

Если требование упорядочения состоит в том, чтобы упорядочить итерацию по последней букве в каждой строке (и если буква такая же, то использовать следующую букву), то можно определитьfunction и затем использовать его при сортировке. В приведенном ниже примере определяется функция, которая переворачивает переданную ей строку, а затем эта функция используется в качестве аргумента дляkey:

>>>

>>> def reverse_word(word):
...     return word[::-1]
...
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=reverse_word)
['banana', 'pie', 'book', 'Washington']

Синтаксис срезаword[::-1] используется для обращения строки. К каждому элементу будет примененreverse_word(), и порядок сортировки будет основан на символах в обратном слове.

Вместо написания отдельной функции вы можете использовать функциюlambda, определенную в аргументеkey.

Alambda — анонимная функция, которая:

  1. Должен быть определен в строке

  2. Не имеет имени

  3. Не может содержатьstatements

  4. Будет исполняться как функция

В приведенном ниже примереkey определяется какlambda без имени, аргумент, принимаемыйlambda, равенx, аx[::-1] — это операция что будет выполнено с аргументом:

>>>

>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=lambda x: x[::-1])
['banana', 'pie', 'book', 'Washington']

x[::-1] вызывается для каждого элемента и меняет слово. Этот обратный вывод затем используется для сортировки, но исходные слова все еще возвращаются.

Если требование изменится и порядок также должен быть изменен, тогда ключевое словоreverse можно использовать вместе с аргументомkey:

>>>

>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=lambda x: x[::-1], reverse=True)
['Washington', 'book', 'pie', 'banana']

Функцииlambda также полезны, когда вам нужно отсортировать объектыclass на основе свойства. Если у вас есть группа учеников и вам нужно отсортировать их по итоговой оценке, от самой высокой к самой низкой, тоlambda можно использовать для получения свойстваgrade изclass:

>>>

>>> from collections import namedtuple

>>> StudentFinal = namedtuple('StudentFinal', 'name grade')
>>> bill = StudentFinal('Bill', 90)
>>> patty = StudentFinal('Patty', 94)
>>> bart = StudentFinal('Bart', 89)
>>> students = [bill, patty, bart]
>>> sorted(students, key=lambda x: getattr(x, 'grade'), reverse=True)
[StudentFinal(name='Patty', grade=94), StudentFinal(name='Bill', grade=90), StudentFinal(name='Bart', grade=89)]

В этом примереnamedtuple используется для создания классов с атрибутамиname иgrade. lambda вызываетgetattr() для каждого элемента и возвращает значение дляgrade.

reverse устанавливается вTrue, чтобы восходящий вывод был перевернут на нисходящий, чтобы первыми располагались самые высокие оценки.

Возможности упорядочивания безграничны, если вы используете аргументы ключевого словаkey иreverse вsorted(). Код может быть чистым и коротким, если вы используете базовыйlambda для небольшой функции, или вы можете написать совершенно новую функцию, импортировать ее и использовать в ключевом аргументе.

Значения для заказа с.sort()

.sort() с очень похожим названием немного отличается от встроенногоsorted(). Они выполняют более или менее то же самое, но документацияhelp() дляlist.sort() выделяет два наиболее важных различия между.sort() иsorted():

>>>

>>> # Python2
Help on method_descriptor:

sort(...)
    L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
    cmp(x, y) -> -1, 0, 1

>>> # Python3
>>> help(list.sort)
Help on method_descriptor:

sort(...)
    L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*

Во-первых, sort — это метод классаlist и может использоваться только со списками. Это не встроенная функция с передаваемой ей итерацией.

Во-вторых,.sort() возвращаетNone и изменяет значения на месте. Давайте посмотрим на влияние обоих этих различий в коде:

>>>

>>> values_to_sort = [5, 2, 6, 1]
>>> # Try to call .sort() like sorted()
>>> sort(values_to_sort)
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'sort' is not defined

>>> # Try to use .sort() on a tuple
>>> tuple_val = (5, 1, 3, 5)
>>> tuple_val.sort()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'tuple' object has no attribute 'sort'

>>> # Sort the list and assign to new variable
>>> sorted_values = values_to_sort.sort()
>>> print(sorted_values)
None

>>> # Print original variable
>>> print(values_to_sort)
[1, 2, 5, 6]

В этом примере кода есть довольно существенные различия в том, как работает.sort() по сравнению сsorted():

  1. Нет упорядоченного вывода.sort(), поэтому присвоение новой переменной передает только типNone.

  2. Списокvalues_to_sort был изменен, и исходный порядок никоим образом не сохраняется.

Эти различия в поведении делают.sort() иsorted() абсолютно не взаимозаменяемыми в коде, и они могут привести к совершенно неожиданным результатам, если один из них используется неправильно.

.sort() имеет те же необязательные аргументы ключевого словаkey иreverse, которые обеспечивают ту же надежную функциональность, что иsorted(). Здесь вы можете отсортировать список фраз по второй букве третьего слова и вернуть список в обратном порядке:

>>>

>>> phrases = ['when in rome',
...     'what goes around comes around',
...     'all is fair in love and war'
...     ]
>>> phrases.sort(key=lambda x: x.split()[2][1], reverse=True)
>>> phrases
['what goes around comes around', 'when in rome', 'all is fair in love and war']

В этом примереlambda используется для следующих действий:

  1. Разделить каждую фразу в список слов

  2. Найти третий элемент или слово в этом случае

  3. Найдите в этом слове вторую букву

Когда использоватьsorted(), а когда использовать.sort()

Вы видели разницу междуsorted() и.sort(), но когда вы используете что?

Допустим, скоро будет 5к гонка: первый ежегодный питон 5к. Данные из гонки должны быть собраны и отсортированы. Данные, которые должны быть получены, это номер нагрудника бегуна и количество секунд, которое потребовалось, чтобы закончить гонку:

>>>

>>> from collections import namedtuple

>>> Runner = namedtuple('Runner', 'bibnumber duration')

Когда бегуны пересекают финишную черту, каждыйRunner будет добавлен в список под названиемrunners. В гонках 5k не все бегуны пересекают стартовую линию одновременно, поэтому первый человек, который пересечет финишную черту, на самом деле не может быть самым быстрым человеком:

>>>

>>> runners = []
>>> runners.append(Runner('2528567', 1500))
>>> runners.append(Runner('7575234', 1420))
>>> runners.append(Runner('2666234', 1600))
>>> runners.append(Runner('2425234', 1490))
>>> runners.append(Runner('1235234', 1620))
>>> # Thousands and Thousands of entries later...
>>> runners.append(Runner('2526674', 1906))

Каждый раз, когда бегун пересекает финишную черту, его номер и общая продолжительность в секундах добавляются кrunners.

Теперь опытный программист, отвечающий за обработку итоговых данных, видит этот список, знает, что топ-5 самых быстрых участников — победители, которые получают призы, а оставшиеся бегуны будут отсортированы по быстрейшему времени.

Не существует требований для нескольких типов сортировки по различным атрибутам. Список разумного размера. Там нет упоминания о хранении списка где-то. Просто отсортируйте по продолжительности и возьмите пять участников с наименьшей продолжительностью:

>>>

>>> runners.sort(key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners[:5]

Программист решает использоватьlambda в аргументеkey, чтобы получить атрибутduration от каждого бегуна и отсортироватьrunners на месте, используя.sort(). После сортировкиrunners первые 5 элементов сохраняются вtop_five_runners.

Миссия выполнена! Приходит директор гонки и сообщает программисту, что, поскольку текущая версия Python 3.7, они решили, что каждый тридцать седьмой человек, который пересек финишную черту, получит бесплатную спортивную сумку.

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

Если вы работаете с важными данными и есть даже небольшая вероятность того, что исходные данные потребуется восстановить, то.sort() — не лучший вариант. Если данные являются копией, если это неважные рабочие данные, или если никто не будет возражать против их потери, потому что их можно восстановить, то.sort() может быть прекрасным вариантом.

В качестве альтернативы участники могли быть отсортированы с использованиемsorted() и того жеlambda:

>>>

>>> runners_by_duration = sorted(runners, key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners_by_duration[:5]

В этом сценарии сsorted() исходный список участников остается неизменным и не был перезаписан. Импровизированное требование найти каждого тридцать седьмого человека, чтобы пересечь финишную черту, может быть достигнуто путем взаимодействия с исходными значениями:

>>>

>>> every_thirtyseventh_runners = runners[::37]

every_thirtyseventh_runners создается с использованием шага в синтаксисе среза списка наrunners, который по-прежнему содержит исходный порядок, в котором бегуны пересекли финишную черту.

Как сортировать в Python: заключение

.sort() иsorted() могут обеспечить именно тот порядок сортировки, который вам нужен, если вы правильно используете их с необязательными аргументами ключевого словаreverse иkey.

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

Для заядлых Pythonistas, ищущих проблемы с сортировкой, попробуйте использовать более сложные типы данных в сортировке: вложенные итерации. Кроме того, не стесняйтесь погрузиться в реализации кода Python с открытым исходным кодом для встроенных модулей и прочитать об используемом в Python алгоритме сортировки под названиемTimsort.

Сортировка в Python выполняется функцией sorted(), если это итерируемые объекты, и методом list.sort(), если это список. Рассмотрим подробнее, как это работало в старых версиях и как работает сейчас.

Примечание Вы читаете улучшенную версию некогда выпущенной нами статьи.

1

Основы сортировки

Так как отсортировать список Python? Для сортировки по возрастанию достаточно вызвать функцию сортировки Python sorted(), которая вернёт новый отсортированный список:

>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]

Для сортировки списка Python также можно использовать метод списков list.sort(), который изменяет исходный список (и возвращает None во избежание путаницы). Обычно Python sort list не так удобен, как использование sorted(), но если вам не нужен исходный список, то так будет немного эффективнее:

>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]

Прим.перев. В Python вернуть None и не вернуть ничего — одно и то же.

Ещё одно отличие заключается в том, что метод list.sort() определён только для списков, в то время как функция sorted Python работает со всеми итерируемыми объектами. Грубо говоря, функция sort Python сортирует список и сохраняет его в отсортированном виде, в то время как функция sorted Питон создаёт новый отсортированный список без изменения исходного.

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})
[1, 2, 3, 4, 5]

Прим.перев. При итерировании по словарю Python возвращает его ключи. Если вам нужны их значения или пары «ключ-значение», используйте методы dict.values() и dict.items() соответственно.

Рассмотрим основные функции сортировки Python.

2

Функции-ключи

С версии Python 2.4 у list.sort() и sorted() появился параметр key для указания функции, которая будет вызываться на каждом элементе до сравнения. Вот регистронезависимое сравнение строк:

>>> sorted("This is a test string from Andrew".split(), key=str.lower)
['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

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

Часто можно встретить код, где сложный объект сортируется по одному из его индексов. Например:

>>> student_tuples = [
        ('john', 'A', 15),
        ('jane', 'B', 12),
        ('dave', 'B', 10),
    ]
>>> sorted(student_tuples, key=lambda student: student[2])   # сортируем по возрасту
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Тот же метод работает для объектов с именованными атрибутами:

>>> class Student:
        def __init__(self, name, grade, age):
            self.name = name
            self.grade = grade
            self.age = age
        def __repr__(self):
            return repr((self.name, self.grade, self.age))
        def weighted_grade(self):
            return 'CBA'.index(self.grade) / self.age

>>> student_objects = [
        Student('john', 'A', 15),
        Student('jane', 'B', 12),
        Student('dave', 'B', 10),
    ]
>>> sorted(student_objects, key=lambda student: student.age)   # сортируем по возрасту
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]​

3

Функции модуля operator

Показанные выше примеры функций-ключей встречаются настолько часто, что Python предлагает удобные функции, чтобы сделать всё проще и быстрее. Модуль operator содержит функции itemgetter(), attrgetter() и, начиная с Python 2.6, methodcaller(). С ними всё ещё проще:

>>> from operator import itemgetter, attrgetter, methodcaller

>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Функции operator дают возможность использовать множественные уровни сортировки массива Python. Отсортируем учеников сначала по оценке, а затем по возрасту:

>>> sorted(student_tuples, key=itemgetter(1, 2))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

>>> sorted(student_objects, key=attrgetter('grade', 'age'))
[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

Используем функцию methodcaller() для сортировки учеников по взвешенной оценке:

>>> [(student.name, student.weighted_grade()) for student in student_objects]
[('john', 0.13333333333333333), ('jane', 0.08333333333333333), ('dave', 0.1)]
>>> sorted(student_objects, key=methodcaller('weighted_grade'))
[('jane', 'B', 12), ('dave', 'B', 10), ('john', 'A', 15)]

4

У list.sort() и sorted() есть параметр reverse, принимающий boolean-значение. Он нужен для обозначения сортировки по убыванию. Отсортируем учеников по убыванию возраста:

>>> sorted(student_tuples, key=itemgetter(2), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

>>> sorted(student_objects, key=attrgetter('age'), reverse=True)
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

5

Стабильность сортировки и сложные сортировки в Python

Начиная с версии Python 2.2, сортировки гарантированно стабильны: если у нескольких записей есть одинаковые ключи, их порядок останется прежним. Пример:

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> sorted(data, key=itemgetter(0))
[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

Обратите внимание, что две записи с 'blue' сохранили начальный порядок. Это свойство позволяет составлять сложные сортировки путём постепенных сортировок. Далее мы сортируем данные учеников сначала по возрасту в порядке возрастания, а затем по оценкам в убывающем порядке, чтобы получить данные, отсортированные в первую очередь по оценке и во вторую — по возрасту:

>>> s = sorted(student_objects, key=attrgetter('age'))     # сортируем по вторичному ключу
>>> sorted(s, key=attrgetter('grade'), reverse=True)       # по первичному
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Алгоритмы сортировки Python вроде Timsort проводят множественные сортировки так эффективно, потому что может извлечь пользу из любого порядка, уже присутствующего в наборе данных.

6

Декорируем-сортируем-раздекорируем

  1. Сначала исходный список пополняется новыми значениями, контролирующими порядок сортировки.
  2. Затем новый список сортируется.
  3. После этого добавленные значения убираются, и в итоге остаётся отсортированный список, содержащий только исходные элементы.

Вот так можно отсортировать данные учеников по оценке:

>>> decorated = [(student.grade, i, student) for i, student in enumerate(student_objects)]
>>> decorated.sort()
>>> [student for grade, i, student in decorated]               # раздекорируем
[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

Это работает из-за того, что кортежи сравниваются лексикографически, сравниваются первые элементы, а если они совпадают, то сравниваются вторые и так далее.

Не всегда обязательно включать индекс в декорируемый список, но у него есть преимущества:

  1. Сортировка стабильна — если у двух элементов одинаковый ключ, то их порядок не изменится.
  2. У исходных элементов не обязательно должна быть возможность сравнения, так как порядок декорированных кортежей будет определяться максимум по первым двум элементам. Например, исходный список может содержать комплексные числа, которые нельзя сравнивать напрямую.

Ещё эта идиома называется преобразованием Шварца в честь Рэндела Шварца, который популяризировал её среди Perl-программистов.

Для больших списков и версий Python ниже 2.4, «декорируем-сортируем-раздекорируем» будет оптимальным способом сортировки. Для версий 2.4+ ту же функциональность предоставляют функции-ключи.

7

Использование параметра cmp

Все версии Python 2.x поддерживали параметр cmp для обработки пользовательских функций сравнения. В Python 3.0 от этого параметра полностью избавились. В Python 2.x в sort() можно было передать функцию, которая использовалась бы для сравнения элементов. Она должна принимать два аргумента и возвращать отрицательное значение для случая «меньше чем», положительное — для «больше чем» и ноль, если они равны:

>>> def numeric_compare(x, y):
        return x - y
>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)
[1, 2, 3, 4, 5]

Можно сравнивать в обратном порядке:

>>> def reverse_numeric(x, y):
        return y - x
>>> sorted([5, 2, 4, 1, 3], cmp=reverse_numeric)
[5, 4, 3, 2, 1]

При портировании кода с версии 2.x на 3.x может возникнуть ситуация, когда нужно преобразовать пользовательскую функцию для сравнения в функцию-ключ. Следующая обёртка упрощает эту задачу по Python:

def cmp_to_key(mycmp):
    'Перевести cmp=функция в key=функция'
    class K(object):
        def __init__(self, obj, *args):
            self.obj = obj
        def __lt__(self, other):
            return mycmp(self.obj, other.obj) < 0
        def __gt__(self, other):
            return mycmp(self.obj, other.obj) > 0
        def __eq__(self, other):
            return mycmp(self.obj, other.obj) == 0
        def __le__(self, other):
            return mycmp(self.obj, other.obj) <= 0
        def __ge__(self, other):
            return mycmp(self.obj, other.obj) >= 0
        def __ne__(self, other):
            return mycmp(self.obj, other.obj) != 0
    return K

Чтобы произвести преобразование, оберните старую функцию:

>>> sorted([5, 2, 4, 1, 3], key=cmp_to_key(reverse_numeric))
[5, 4, 3, 2, 1]

В Python 2.7 функция cmp_to_key() была добавлена в модуль functools.

8

Поддержание порядка сортировки

В стандартной библиотеке Python нет модулей, аналогичных типам данных C++ вроде set и map. Python делегирует эти задачи сторонним библиотекам, доступным в Python Package Index: они используют различные методы для сохранения типов list, dict и set в отсортированном порядке. Поддержание порядка с помощью специальной структуры данных может помочь избежать очень медленного поведения (квадратичного времени выполнения) при наивном подходе с редактированием и постоянной пересортировкой данных. Вот некоторые из модулей, реализующих эти типы данных:

  • SortedContainers — реализация сортированных типов list, dict и set на чистом Python, по скорости не уступает реализациям на C. Тестирование включает 100% покрытие кода и многие часы стресс-тестирования. В документации можно найти полный справочник по API, сравнение производительности и руководства по внесению своего вклада.
  • rbtree — быстрая реализация на C для типов dict и set. Реализация использует структуру данных, известную как красно-чёрное дерево.
  • treap — сортированный dict. В реализации используется Декартово дерево, а производительность улучшена с помощью Cython.
  • bintrees — несколько реализаций типов dict и set на основе деревьев на C. Самые быстрые основаны на АВЛ и красно-чёрных деревьях. Расширяет общепринятый API для предоставления операций множеств для словарей.
  • banyan — быстрая реализация dict и set на C.
  • skiplistcollections — реализация на чистом Python, основанная на списках с пропусками, предлагает ограниченный API для типов dict и set.
  • blist — предоставляет сортированные типы list, dict и set, основанные на типе данных «blist», реализация на Б-деревьях. Написано на Python и C.

9

Прочее

Для сортировки с учётом языка используйте locale.strxfrm() в качестве ключевой функции или locale.strcoll() в качестве функции сравнения. Параметр reverse всё ещё сохраняет стабильность сортировки. Этот эффект можно сымитировать без параметра, использовав встроенную функцию reversed() дважды:

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]
>>> assert sorted(data, reverse=True) == list(reversed(sorted(reversed(data))))

Чтобы создать стандартный порядок сортировки для класса, просто добавьте реализацию соответствующих методов сравнения:

>>> Student.__eq__ = lambda self, other: self.age == other.age
>>> Student.__ne__ = lambda self, other: self.age != other.age
>>> Student.__lt__ = lambda self, other: self.age < other.age
>>> Student.__le__ = lambda self, other: self.age <= other.age
>>> Student.__gt__ = lambda self, other: self.age > other.age
>>> Student.__ge__ = lambda self, other: self.age >= other.age
>>> sorted(student_objects)
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Для типов, сравнение которых работает обычным образом, рекомендуется определять все 6 операторов. Декоратор классов functools.total_ordering упрощает их реализацию. Функциям-ключам не нужен доступ к внутренним данным сортируемых объектов. Они также могут осуществлять доступ к внешним ресурсам. Например, если оценки ученика хранятся в словаре, их можно использовать для сортировки отдельного списка с именами учеников:

>>> students = ['dave', 'john', 'jane']
>>> newgrades = {'john': 'F', 'jane':'A', 'dave': 'C'}
>>> sorted(students, key=newgrades.__getitem__)
['jane', 'dave', 'john']

Надеемся, теория по Python list sort и соответствующие задачи по Питону с разбором были для вас полезны. Вас также может заинтересовать статьи:

  • Хочу научиться программировать на Python. С чего начать?
  • Хочу научиться программировать на Python: инструкция для продолжающих

Перевод статьи «Sorting Mini-HOW TO»

На чтение 3 мин Просмотров 1.1к. Опубликовано 03.02.2023

Содержание

  1. Введение
  2. Первый способ – цикл while
  3. Второй способ – цикл for
  4. Третий способ – путём преобразования строки в список
  5. Четвёртый способ – срез
  6. Заключение

Введение

В ходе статьи рассмотрим целых четыре способа поменять порядок цифр числа на обратный в Python.

Первый способ – цикл while

Для начала дадим пользователю возможность ввести число, и создадим переменную number2 равную нулю:

number = int(input("Введите число: "))
number2 = 0

Создадим цикл while, который не закончится, пока number больше нуля:

number = int(input("Введите число: "))
number2 = 0

while number > 0:

Внутри цикла в переменную digit сохраняем последнюю цифру переменной number, полученную благодаря делению с остатком на десять:

number = int(input("Введите число: "))
number2 = 0

while number > 0:
    digit = number % 10

Удаляем последнюю цифру из переменной number путём деления без остатка на десять:

number = int(input("Введите число: "))
number2 = 0

while number > 0:
    digit = number % 10
    number = number // 10

Увеличим разрядность number2 путём умножения на десять:

number = int(input("Введите число: "))
number2 = 0

while number > 0:
    digit = number % 10
    number = number // 10
    number2 = number2 * 10

Осталось прибавить к number2 значение из переменной digit, и после цикла вывести результат:

number = int(input('Введите число: '))
number2 = 0

while number > 0:
    digit = number % 10
    number = number // 10
    number2 = number2 * 10
    number2 = number2 + digit

print(f"Заданное число в противоположном порядке: {number2}")

# Введите число: 345456
# Заданное число в противоположном порядке: 654543

Второй способ – цикл for

Второй способ работает по тому же принципу, что и первый, но вместо цикла while используется цикл for:

number = int(input('Введите число: '))
number2 = 0

for i in enumerate(str(number)):
    digit = number % 10
    number = number // 10
    number2 = number2 * 10
    number2 = number2 + digit

print(f"Заданное число в противоположном порядке: {number2}")

Третий способ – путём преобразования строки в список

Для начала преобразуем строку с введённым числом в список:

number = input("Введите целое число: ")
number = list(number)

С помощью метода reverse() развернём полученный список:

number = input("Введите целое число: ")
number = list(number)
number.reverse()

Превратим итоговый список в строку и выведем результат:

number = input("Введите целое число: ")
number = list(number)
number.reverse()
number = "".join(number)
print(f"Заданное число в противоположном порядке: {number}")

Четвёртый способ – срез

Ну и в последнем способе, который мы рассмотрим будет задействован срез.

Развернём введённое число используя срез из с первого до последнего символа с обратным шагом и выведем результат:

number = input("Введите целое число: ")
number = number[::-1]
print(f"Заданное число в противоположном порядке: {number}")

Заключение

В ходе статьи мы с Вами рассмотрели четыре способа поменять порядок цифр числа на обратный в Python. Надеюсь Вам понравилась статья, желаю удачи и успехов! 🙂

Admin

Понравилась статья? Поделить с друзьями:
  • Как найти своего мужчину на сайте знакомств
  • Как составить схему к задаче на сколько больше
  • Потерял машину на парковке как найти
  • Как найти с нус угла
  • Ошибка р0172 приора как исправить