Ответ 1
Как списки и другие последовательности сравниваются в Python?
Списки (и другие последовательности) в Python сравниваются лексикографически и не основаны ни на каком другом параметре.
Объекты последовательности могут сравниваться с другими объектами с тем же типом последовательности. Сравнение использует лексикографическое упорядочение: сначала сравниваются первые два элемента, и если они отличаются друг от друга, это определяет результат сравнения; если они равны, сравниваются следующие два элемента и так далее, пока не будет исчерпана любая последовательность.
Что такое лексикографическая сортировка?
На странице Википедии лексикографическая сортировка
лексикографический или лексикографический порядок (также известный как лексический порядок, словарьный порядок, алфавитный порядок или лексикографический (al) продукт) является обобщением того, как алфавитный порядок слов основан на алфавитном порядке их составляющих букв.
Функция min
возвращает наименьшее значение в iterable. Таким образом, лексикографическое значение [1,2]
является наименьшим в этом списке. Вы можете проверить, используя [1,2,21]
>>> my_list=[[1,2,21],[1,3],[1,2]]
>>> min(my_list)
[1, 2]
Что происходит в этом случае min
?
Переход на элемент my_list
, во-первых, [1,2,21]
и [1,3]
. Теперь из документов
Если два элемента, которые нужно сравнить, сами являются последовательностями одного и того же типа, лексикографическое сравнение выполняется рекурсивно.
Таким образом, значение [1,1,21]
меньше [1,3]
, потому что второй элемент [1,3]
, который равен 3
, лексикографически выше значения второго элемента [1,1,21]
, который, 1
.
Теперь сравниваем [1,2]
и [1,2,21]
и добавляем еще одну ссылку из документов
Если одна последовательность представляет собой начальную подпоследовательность другой, более короткая последовательность представляет собой меньшую (меньшую).
[1,2]
- начальная подпоследовательность [1,2,21]
. Поэтому значение [1,2]
в целом меньше, чем значение [1,2,21]
. Следовательно, в качестве вывода возвращается [1,2]
.
Это можно проверить с помощью функции sorted
>>> sorted(my_list)
[[1, 2], [1, 2, 21], [1, 3]]
Что делать, если в списке есть несколько минимальных элементов?
Если список содержит повторяющиеся минимальные элементы, возвращается первый
>>> my_list=[[1,2],[1,2]]
>>> min(my_list)
[1, 2]
Это можно подтвердить, используя вызов функции id
>>> my_list=[[1,2],[1,2]]
>>> [id(i) for i in my_list]
[140297364849368, 140297364850160]
>>> id(min(my_list))
140297364849368
Что мне нужно сделать для предотвращения лексикографического сравнения в min
?
Если требуемое сравнение не является лексикографическим, можно использовать аргумент key
(как указано Padraic)
Функция min
имеет дополнительный необязательный аргумент key
. Аргумент key
принимает функцию.
Необязательный ключевой аргумент указывает функцию упорядочения с одним аргументом как и для
list.sort()
. Ключевой аргумент, если он поставлен, должен быть в форме ключевого слова (например,min(a,b,c,key=func)
).
Например, если нам нужен наименьший элемент по длине, нам нужно использовать функцию len
.
>>> my_list=[[1,2,21],[1,3],[1,2]]
>>> min(my_list,key=len) # Notice the key argument
[1, 3]
Как мы видим, здесь возвращается первый самый короткий элемент.
Что делать, если список неоднороден?
До Python2
Если список является гетерогенным , имена типов рассматриваются для заказа, проверьте Сравнения,
Объекты разных типов, кроме чисел, упорядочиваются по именам типов
Следовательно, если вы поместите int
и list
, вы получите целочисленное значение как наименьшее, так как i
имеет меньшее значение, чем l
. Аналогично '1'
будет иметь более высокую ценность, чем обе эти.
>>> my_list=[[1,1,21],1,'1']
>>> min(my_list)
1
Python3 и далее
Однако эта запутанная техника была удалена в Python3. Теперь он вызывает TypeError
. Прочитайте Что нового в Python 3.0
Операторы сравнения порядка (
<
,<=
,>=
,>
) создают исключениеTypeError
, когда операнды не имеют значимого естественного упорядочения. Таким образом, выражения типа1 < ''
,0 > None
илиlen <= len
более недействительны и, например,None < None
вызываетTypeError
вместо возвратаFalse
. Следствием является то, что сортировка гетерогенного списка больше не имеет смысла - все элементы должны быть сопоставимы друг с другом.
>>> my_list=[[1,1,21],1,'1']
>>> min(my_list)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < list()
Но он работает для типов Comparable, например
>>> my_list=[1,2.0]
>>> min(my_list)
1
Здесь мы видим, что list
содержит значения float
и int
. Но поскольку float
и int
являются сопоставимыми типами, в этом случае работает функция min
.