Python3样式排序-新的密钥机制中的旧cmp方法功能吗? [英] Python3 style sorting -- old cmp method functionality in new key mechanism?

查看:83
本文介绍了Python3样式排序-新的密钥机制中的旧cmp方法功能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了有关包装函数的信息,该函数将cmp样式比较移入了删除了cmp功能的Python 3中的键样式比较.

I read about the wrapper function to move a cmp style comparison into a key style comparison in Python 3, where the cmp capability was removed.

我花了很多时间来思考Python3直键样式sorted()函数的功能,至少据我了解,仅为该键指定了一项,可以让您正确比较,例如,两个IP用于订购.还是火腿电话.

I'm having a heck of a time wrapping my head around how a Python3 straight key style sorted() function, with, at least as I understand it, just one item specified for the key, can allow you to properly compare, for instance, two IPs for ordering. Or ham calls.

与cmp无关,它没有什么:sorted()和sort()用两个ip调用了您,您查看了适当的部分,做出了决定,完成了.

Whereas with cmp there was nothing to it: sorted() and sort() called you with the two ips, you looked at the appropriate portions, made your decisions, done.

def ipCompare(dqA,dqB):
    ...

ipList = sorted(ipList,cmp=ipCompare)

与火腿无线电通话相同.排序不是字母顺序的;电话通常是字母+数字+字母;首先排序的优先级是数字部分,然后是第一个字母,然后是最后一个字母

Same thing with ham radio calls. The sorting isn't alphabetic; the calls are generally letter(s)+number(s)+letter(s); the first sorting priority is the number portion, then the first letter(s), then the last letter(s.)

使用cmp ...不流汗.

Using cmp... no sweat.

def callCompare(callA,callB):
    ...

hamlist = sorted(hamlist,cmp=callCompare)

使用Python3 ...无需经历包装程序的跳动...并传递一项...我想...该怎么办?

With Python3... without going through the hoop jumping of the wrapper... and being passed one item... I think... how can that be done?

如果绝对需要包装器...那么为什么要首先在Python3中删除cmp?

And if the wrapper is absolutely required... then why remove cmp within Python3 in the first place?

我确定我错过了一些东西.我只是看不到. :/

I'm sure I'm missing something. I just can't see it. :/

好的,现在我知道我所缺少的. IPs的解决方案在下面的答案中给出.这是我想到的用于对常见前缀,区域,后缀形式的火腿调用进行排序的键:

ok, now I know what I was missing. Solutions for IPs were given in the answers below. Here's a key I came up with for sorting ham calls of the common prefix, region, postfix form:

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结果为['na1a','W1AW','N4EJI','AA7AS']

详细信息:

  • AA7AScallKey()出来为7,AA,AS
  • N4EJIcallKey()出来为4,N,EJI
  • W1AWcallKey()中出来为1,W,AW
  • na1acallKey()出来为1,NA,A
  • AA7AS comes out of callKey() as 7,AA,AS
  • N4EJI comes out of callKey() as 4,N,EJI
  • W1AW comes out of callKey() as 1,W,AW
  • na1a comes out of callKey() as 1,NA,A

推荐答案

首先,如果您尚未阅读排序方法,一定要读懂;一开始它可能解释不了很多.

First, if you haven't read the Sorting HOWTO, definitely read that; it explains a lot that may not be obvious at first.

对于第一个示例,两个IPv4地址,答案非常简单.

For your first example, two IPv4 addresses, the answer is pretty simple.

要比较两个地址,一件显而易见的事情是将它们都从点分四个字符串转换为4个整数的元组,然后只需比较元组即可:

To compare two addresses, one obvious thing to do is convert them both from dotted-four strings into tuples of 4 ints, then just compare the tuples:

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也是如此:

An even better thing to do is convert them to some kind of object that represents an IP address and has comparison operators. In 3.4+, the stdlib has such an object built in; let's pretend 2.7 did as well:

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

很明显,它们都更容易作为关键功能:

It should be obvious that these are both even easier as key functions:

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

def key_ip(ip):
    return ipaddress.ip_address(ip)


对于第二个示例,火腿无线电呼号:为了编写cmp函数,您必须能够将每个火腿地址分解为字母,数字,字母部分,然后比较数字,然后比较第一个字母,然后比较第二个字母.为了编写key函数,您必须能够将火腿地址分解为字母,数字,字母部分,然后返回一个元组(数字,第一个字母,第二个字母).同样,键功能实际上是更简单,而不是更难.


For your second example, ham radio callsigns: In order to write a cmp function, you have to be able to break each ham address into the letters, numbers, letters portions, then compare the numbers, then compare the first letters, then compare the second letters. In order to write a key function, you have to be able to break down a ham address into the letters, numbers, letters portions, then return a tuple of (numbers, first letters, second letters). Again the key function is actually easier, not harder.

实际上,任何人都能想到的 most 例子就是这种情况.最复杂的比较最终归结为将复杂的部分转换为某些部分的序列,然后对该序列进行简单的字典比较.

And really, this is the case for most examples anyone was able to come up with. Most complicated comparisons ultimately come down to a complicated conversion into some sequence of parts, and then simple lexicographical comparison of that sequence.

这就是为什么cmp函数在2.4版本中已被弃用,而在3.0版本中最终被删除的原因.

That's why cmp functions were deprecated way back in 2.4 and finally removed in 3.0.

当然,在某些情况下,cmp函数更易于阅读-人们尝试提出的大多数示例都是错误的,但也有一些示例.而且还有已经使用了20年的代码,没有人愿意以新的术语重新思考它,而没有任何好处.对于这些情况,您已经 cmp_to_key .

Of course there are some cases where a cmp function is easier to read—most of the examples people try to come up with turn out to be wrong, but there are some. And there's also code which has been working for 20 years and nobody wants to rethink it in new terms for no benefit. For those cases, you've got cmp_to_key.

实际上,还有另一个原因被弃用,除了这个原因,也许还有三分之一.

There's actually another reason cmp was deprecated, on top of this one, and maybe a third.

在Python 2.3中,类型具有__cmp__方法,该方法用于处理所有运算符.在2.4中,他们增加了六个方法__lt____eq__等作为替代.这样可以提供更大的灵活性-例如,您可以选择非总排序的类型.因此,将2.3与a < b进行比较时,实际上是在做a.__cmp__(b) < 0,它以一种非常明显的方式映射到cmp自变量.但是在2.4+中,a < b会执行a.__lt__(b),而事实并非如此.多年来,这使很多人感到困惑,同时删除__cmp__cmp排序函数参数也消除了这种困惑.

In Python 2.3, types had a __cmp__ method, which was used for handling all of the operators. In 2.4, they grew the six methods __lt__, __eq__, etc. as a replacement. This allows for more flexibility—e.g., you can have types that aren't total-ordered. So, 2.3's when compared a < b, it was actually doing a.__cmp__(b) < 0, which maps in a pretty obvious way to a cmp argument. But in 2.4+, a < b does a.__lt__(b), which doesn't. This confused a lot of people over the years, and removing both __cmp__ and the cmp argument to sort functions removed that confusion.

同时,如果您阅读了Sorting HOWTO,您会注意到,在我们使用cmp之前,做这种事情的唯一方法是decorate-sort-unecorate(DSU).请注意,如何将良好的key函数映射到良好的DSU排序是一目了然的,反之亦然,但是对于cmp函数,这绝对不是显而易见的.我不记得有人在py3k列表上明确提到过这个,但是我怀疑人们在决定是否最终永久杀死cmp时可能已经想到了.

Meanwhile, if you read the Sorting HOWTO, you'll notice that before we had cmp, the only way to do this kind of thing was decorate-sort-undecorate (DSU). Notice that it's blindly obvious how to map a good key function to a good DSU sort and vice-versa, but it's definitely not obvious with a cmp function. I don't remember anyone explicitly mentioning this one on the py3k list, but I suspect people may have had it in their heads when deciding whether to finally kill cmp for good.

这篇关于Python3样式排序-新的密钥机制中的旧cmp方法功能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆