Сортировка стиля Python3 – функция старого cmp-метода в новом ключевом механизме?

Я прочитал о функции-оболочке, чтобы переместить сравнение стиля cmp в сравнение стиля ключа в Python 3, где была удалена возможность cmp.

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

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

def ipCompare(dqA,dqB): ... ipList = sorted(ipList,cmp=ipCompare) 

То же самое происходит с радиолюбителями. Сортировка не является алфавитной; вызовы обычно означают букву (ы) + число (ы) + букву (ы); первым приоритетом сортировки является числовая часть, затем первая буква (буквы), затем последняя буква (s.)

Использование cmp … нет пота.

 def callCompare(callA,callB): ... hamlist = sorted(hamlist,cmp=callCompare) 

С Python3 … не проходя через обруч, прыгающий с оберткой … и передается один предмет … Я думаю … как это можно сделать?

И если оболочка абсолютно необходима … то зачем сначала удалять cmp внутри Python3?

Я уверен, что я что-то упустил. Я просто не вижу этого. : /


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

 import re def callKey(txtCall): l = re.split('([0-9]*)',txtCall.upper(),1) return l[1],l[0],l[2] hamList = ['N4EJI','W1AW','AA7AS','na1a'] sortedHamList = sorted(hamList,key=callKey) 

sortedHamList result ['na1a','W1AW','N4EJI','AA7AS']

Деталь:

  • AA7AS выходит из callKey() как 7,AA,AS
  • N4EJI выходит из callKey() как 4,N,EJI
  • W1AW выходит из callKey() как 1,W,AW
  • na1a выходит из callKey() как 1,NA,A

2 Solutions collect form web for “Сортировка стиля Python3 – функция старого cmp-метода в новом ключевом механизме?”

Во-первых, если вы не читали « Сортировка HOWTO» , обязательно прочитайте это; это объясняет многое, что может быть не очевидно сразу.


Для вашего первого примера, двух адресов IPv4, ответ довольно прост.

Чтобы сравнить два адреса, нужно сделать одно из них: преобразовать их из четырех строк в четыре строки в кортежи из 4-х целых чисел, а затем сравнить кортежи:

 def cmp_ip(ip1, ip2): ip1 = map(int, ip1.split('.')) ip2 = map(int, ip2.split('.')) return cmp(ip1, ip2) 

Еще лучше сделать это, чтобы преобразовать их в какой-то объект, который представляет IP-адрес и имеет операторы сравнения. В 3.4+, stdlib имеет такой объект, встроенный; давайте сделаем вид 2.7:

 def cmp_ip(ip1, ip2): return cmp(ipaddress.ip_address(ip1), ipaddress.ip_address(ip2)) 

Должно быть очевидно, что это еще проще, чем ключевые функции:

 def key_ip(ip): return map(int, ip.split('.')) def key_ip(ip): return ipaddress.ip_address(ip) 

Для вашего второго примера позывные радиолюбителей: для того, чтобы написать функцию cmp , вы должны иметь возможность разбивать каждый адрес ветчины на буквы, цифры, буквы, затем сравнивать числа, затем сравнивать первые буквы, а затем сравнивать вторых букв. Чтобы написать key функцию, вы должны иметь возможность разбивать адрес ветчины на буквы, цифры, буквы, а затем возвращать кортеж (числа, первые буквы, вторые буквы). Опять же ключевая функция на самом деле проще , а не сложнее .


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

Вот почему функции cmp были устаревшими в 2.4 и окончательно удалены в версии 3.0.


Конечно, есть случаи, когда функция cmp легче читать – большинство примеров, которые люди пытаются придумать, оказываются ошибочными, но есть некоторые. И есть также код, который работает уже 20 лет, и никто не хочет переосмысливать его в новых условиях без какой-либо выгоды. Для этих случаев у вас есть cmp_to_key .


Есть еще одна причина, из-за которой cmp был устарел, поверх этого, а может быть, и третьего.

В Python 2.3 типы имели метод __cmp__ , который использовался для обработки всех операторов. В 2.4 они __lt__ шесть методов __lt__ , __eq__ и т. Д. Это позволяет повысить гибкость, например, вы можете иметь типы, которые не являются полностью упорядоченными. Итак, 2.3 при сравнении a < b , на самом деле он делал a.__cmp__(b) < 0 , что довольно очевидно отображает аргумент cmp . Но в 2.4+ a < b делает a.__lt__(b) , а это не так. Это смутило многих людей на протяжении многих лет, и удаление обоих __cmp__ и аргумента cmp для сортировки функций устранило эту путаницу.

Между тем, если вы прочитаете «Сортировка HOWTO», вы заметите, что до того, как мы получили cmp , единственный способ сделать это – украсить-sort-undecorate (DSU). Обратите внимание, что вслепую очевидна, как сопоставить хорошую key функцию с хорошим сортированием DSU и наоборот, но это определенно не очевидно с помощью функции cmp . Я не помню, чтобы кто-то прямо упоминал об этом в списке py3k, но я подозреваю, что люди, возможно, имели это в своих головах, решая, наконец ли убить cmp навсегда.

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

 def ip_as_components (ip): return map(int, ip.split('.')) sorted_ips = sorted(ips, key=ip_as_components) 

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

Глядя на заказ HAM, он может выглядеть так:

 def ham_to_components (ham_code): # .. decompose components based on ordering of each return (prefix_letters, numbers, postfix_letters) 

key подход (похожий на «порядок по», найденный на других языках), как правило, является более простой и более естественной конструкцией, связанной с этим – если предположить, что исходные типы еще не упорядочены. Основным недостатком этого подхода является то, что частично обратное (например, asc then desc) упорядочение может быть сложным, но оно разрешимо путем возврата вложенных кортежей и т. Д.

В Py3.0 параметр cmp полностью удалялся (как часть более крупного усилия по упрощению и унификации языка , устраняя конфликт между богатыми сравнениями и магическим методом __cmp__() ).

Если абсолютно необходимо sorted с помощью пользовательского «cmp», cmp_to_key можно использовать тривиально.

 sorted_ips = sorted(ips, key=functools.cmp_to_key(ip_compare)) 
  • Поиск медианы списка в Python
  • Сортировка по нескольким параметрам в pyes и elasticsearch
  • Есть ли какая-либо реализация Python2, где упорядочение является транзитивным?
  • Сортировка списка Python по двум критериям
  • Сортировка строковых значений в соответствии с пользовательским алфавитом в Python
  • Python: Как отсортировать массив X, но переносить тот же относительный вид на Y?
  • Как проверить, отсортирован ли список?
  • Преимущества Quichesort
  • Python - лучший язык программирования в мире.