Python列表迭代转为一行代码

5
我目前正在学习Python。
我该怎么表达:
dates = list()  
for entry in some_list:  
    entry_split = entry.split()    
    if len(entry_split) >= 3:  
        date = entry_split[1]
        if date not in dates:  
            dates.append(date)

如何在Python中将多行代码转换为一行?

9
在Python的第一天学习中,长长的一行代码可能不是最好的选择。请尝试使用更简单易懂的方式编写代码。 - Slater Victoroff
3
为什么你想要这样做呢?虽然可以实现,但一行代码可能并不高效且难以理解。只有当一行代码能够提升代码的清晰度时才应该使用它。 - mgilson
可能仍然是一个合法的问题! - Paolo
@mgilson,列表推导式通常比逐个构建列表更快,但由于部分创建的列表的依赖关系,这种情况似乎不适合使用列表推导式。 - Mark Ransom
@MarkRansom -- 没错。在这种情况下,你需要多次拆分字符串,这将抵消你从列表推导中获得的任何加速效果。无论如何,使用列表推导的主要原因是为了代码清晰度,而不是速度。 - mgilson
显示剩余3条评论
5个回答

7

与其用一行代码,也许用三行会更容易理解。

table = (entry.split() for entry in some_list)
raw_dates = (row[1] for row in table if len(row) >= 3)
# Uniquify while keeping order. https://dev59.com/IHRB5IYBdhLWcg3w4bEo#17016257
dates = list(collections.OrderedDict.fromkeys(raw_dates))

我在使用 import collections 时遇到了这个错误:AttributeError: 'module' object has no attribute 'OrderedDict'。有什么遗漏吗? - dfernan
2
@dfernandes__:你需要先import collections。并且你需要使用Python 2.7或3.x版本。 - kennytm
刚刚更新到3.3.2版本,你的解决方案也能正常工作。谢谢! - dfernan

3

如果顺序不重要:

dates = set(split[1] for split in (x.split() for x in some_list) if len(split) >= 3)

当然,如果您想要一个列表而不是一个集合,只需将结果传递给list()。 尽管我可能会坚持使用您现有的方式,因为它更易读。

感谢您的输入,非常有帮助。我会坚持使用现有的方案。 - dfernan

1

假设您的Python版本支持集合推导式,请尝试使用以下代码:

list({d[1] for d in (e.split() for e in some_list) if len(d) >= 3})

如果没有可用的集合推导式,可以使用以下方法:

如果 set comprehensions 不可用,则这将起作用:

list(set(d[1] for d in (e.split() for e in some_list) if len(d) >= 3))

但是,认真地说,把这个代码写成一行并不是一个好主意,因为评论中提到的原因。即使如此,你的代码可以稍微改进一下,使用set来从元素集合中删除重复项:

dates = set()
for entry in some_list:
    entr_split = entry.split()
    if len(entry_split) >= 3:
        dates.add(entry_split[1])
dates = list(dates)

1
不需要分割两次。你可以在子列表中分割,然后在外部检查长度。 - 2rs2ts
1
@2rs2ts 好的,我编辑了我的答案。请注意,在最内层循环中使用生成器表达式而不是列表是推荐的。 - Óscar López
没错,我应该修改我的代码以达到同样的效果。 - 2rs2ts

1
看起来你在将some_list中的每个元素拆分,检查拆分后是否有3个或更多部分,并将第二部分附加到列表中(如果它尚未在列表中)。对于这种最后一种行为,您可以使用set,因为set仅包含唯一元素。
list(set((entry_split[1] for entry_split in (entry.split() for entry in some_list) if len(entry_split) >= 3]))

我将结果重新转换为列表,因为您使用了一个列表。

0
使用列表推导式:
dates = set([entry.split()[1] for entry in some_list if len(entry.split()) >= 3])

这将给我们想要的结果:

>>> some_list = [
... "a 2011-08-04 b",
... "x y",
... "e 2012-03-04 g"
... ]
>>> dates = set([entry.split()[1] for entry in some_list if len(entry.split()) >= 3])
>>> dates
{'2011-08-24', '2012-03-04'}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接