【问题标题】:Python3 Make tie-breaking lambda sort more pythonic?Python3 让打破平局的 lambda 排序更 Pythonic?
【发布时间】:2015-05-14 23:20:23
【问题描述】:

作为 python lambdas 的练习(只是为了让我可以学习如何更正确地使用它们),我给自己分配了一个任务,根据它们的自然字符串顺序以外的东西对一些字符串进行排序。

我从 apache 中获取版本号字符串,然后根据我用正则表达式提取的数字提出一个 lambda 来对它们进行排序。它有效,但我认为它可以更好,我只是不知道如何改进它,所以它更强大。

from lxml import html
import requests
import re

# Send GET request to page and parse it into a list of html links
jmeter_archive_url='https://archive.apache.org/dist/jmeter/binaries/'
jmeter_archive_get=requests.get(url=jmeter_archive_url)
page_tree=html.fromstring(jmeter_archive_get.text)
list_of_links=page_tree.xpath('//a[@href]/text()')

# Filter out all the non-md5s. There are a lot of links, and ultimately
# it's more data than needed for his exercise
jmeter_md5_list=list(filter(lambda x: x.endswith('.tgz.md5'), list_of_links))

# Here's where the 'magic' happens. We use two different regexes to rip the first
# and then the second number out of the string and turn them into integers. We
# then return them in the order we grabbed them, allowing us to tie break.
jmeter_md5_list.sort(key=lambda val: (int(re.search('(\d+)\.\d+', val).group(1)), int(re.search('\d+\.(\d+)', val).group(1))))
print(jmeter_md5_list)

这确实有预期的效果,输出是:

['jakarta-jmeter-2.5.1.tgz.md5', 'apache-jmeter-2.6.tgz.md5', 'apache-jmeter-2.7.tgz.md5', 'apache-jmeter-2.8.tgz.md5', 'apache-jmeter-2.9.tgz.md5', 'apache-jmeter-2.10.tgz.md5', 'apache-jmeter-2.11.tgz.md5', 'apache-jmeter-2.12.tgz.md5', 'apache-jmeter-2.13.tgz.md5']

所以我们可以看到字符串被排序成有意义的顺序。最低版本在前,最高版本在后。我在解决方案中看到的直接问题有两个。

  • 首先,我们必须创建两个不同的正则表达式来获取我们想要的数字,而不是仅仅捕获组 1 和 2。主要是因为我知道没有多行 lambda,我不知道如何重用单个正则表达式对象创造第二个。
  • 其次,这仅适用于版本号是由单个句点分隔的两个数字时。第一个元素是 2.5.1,它被排序到正确的位置,但当前方法不知道如何为 2.5.2 或 2.5.3 或任何具有任意数量的版本点的字符串打平。

所以它有效,但必须有更好的方法来做到这一点。我该如何改进?

【问题讨论】:

  • 对 lambda 的使用不当。为此编写一个小函数更“Pythonic”。
  • @dawg 谢谢,但这已经在 Ignacio Vazquez-Abrams 的回答中得到解决。

标签: sorting python-3.x lambda


【解决方案1】:

这不是一个完整的答案,但它会让你走得更远。

key函数的返回值可以是元组,元组自然排序。您希望 key 函数的输出为:

((2, 5, 1), 'jakarta-jmeter')
((2, 6), 'apache-jmeter')
etc.

请注意,无论如何,这对于 lambda 来说都是一个糟糕的用例。

【讨论】:

  • 您在我给​​出自己的答案时回复了。我明白你在说什么。什么是适当的礼仪?我应该更新自己的答案以匹配您所说的内容,还是应该进行更改,然后将其作为评论发布给您?
【解决方案2】:

最初,我想出了这个:

jmeter_md5_list.sort(key=lambda val: list(map(int, re.compile('(\d+(?!$))').findall(val))))

但是,根据 Ignacio Vazquez-Abrams 的回答,我进行了以下更改。

def sortable_key_from_string(value):
        version_tuple = tuple(map(int, re.compile('(\d+(?!$))').findall(value)))
        match = re.match('^(\D+)', value)
        version_name = ''
        if match:
                version_name = match.group(1)
        return (version_tuple, version_name)

还有这个:

jmeter_md5_list.sort(key = lambda val: sortable_key_from_string(val))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-10
    相关资源
    最近更新 更多