【发布时间】: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