列表推导式用于创建子列表

3
作为一名计算机科学初学者,我被分配编写一个函数将偶数和奇数数字的列表排序为两个子列表。等等...不要对我点踩。我自己在学习并尝试使用列表推导式和timeit,想知道是否能够使用列表推导式来完成更具挑战性的任务。
我已经弄明白了如何使用列表推导式来展开子列表,但反过来似乎不行。这种方法可行吗?
def odd_even_filter(numbers):
    even = []
    odd = []
    for i in numbers:
        if i % 2 == 0:
            even.append(i)
        else:
            odd.append(i)
    return [even, odd]

odd_even_filter([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>[[2,4,6,7],[1,3,5,7,9]]

我只是尝试使用列表推导式将平面列表生成嵌套列表。这可能不值得而且不是Python的做法,但我只是在实验。


您的问题是什么?如何使用列表推导来完成它? - Paulo Bu
5个回答

2
如果你想要最简短的、符合Python风格的答案,那么怎么样呢?
odd = [i for i in numbers if i % 2]  # this is O(n)
even = list(set(numbers) - set(odd)) # this is O(n log n)

一种效率较低但仍然清晰的替代方案是:
even = numbers - odd # this is O(n^2)

一个O(n)的替代方案(最好的方案?)可能是:
odd = [i for i in numbers if i % 2] # this is O(n)
even = [i for i in numbers if not i % 2] # this is O(n)

1

在编写代码时,可读性和紧凑性之间总会存在权衡。在这种情况下,我认为devnull的答案非常出色。他使用了列表推导式和Python的if表达式,在一行中实现了非常易读的效果。如果你的测试标准更严格,通常将条件分离成它们自己的函数更有用。对于你的示例,这些函数将是:

def even(x): return x%2 == 0
def odd(x) : return x%2 != 0

然后使用它们来过滤结果,就像这样:

def oddEvenFilter(x): return [filter(even, x), filter(odd, x)]

这是三行代码,但结合起来非常易读。

0

这个可以工作,但并不容易阅读,因为范围是子组的数量,对于偶数和奇数来说是2。

return [[ n for n in numbers if n % 2 == 0] if i == 0 else [ n for n in numbers if n % 2 != 0] for i in range(2)]

我用timeit测试了一下,执行时间是原来的两倍,这是可以预料的。devnull的答案也需要稍微多花一点时间。

def odd_even_filter(numbers):
    even = []
    odd = []
    for i in numbers:
        if i % 2 == 0:
            even.append(i)
        else:
            odd.append(i)
    return [even, odd]

def odd_even_filter_2(numbers):
    return [[ n for n in numbers if n % 2 == 0] if i == 0 else [ n for n in numbers if n % 2 != 0] for i in range(2)]

def odd_even_filter_3(numbers):
    even = []
    odd = []
    [ odd.append(n) if n % 2 != 0 else even.append(n) for n in numbers]
    return [even,odd]

print(timeit.timeit('odd_even_filter([1, 2, 3, 4, 5, 6, 7, 8, 9])', setup="from __main__ import odd_even_filter" )) 
print(timeit.timeit('odd_even_filter_2([1, 2, 3, 4, 5, 6, 7, 8, 9])', setup="from __main__ import odd_even_filter_2" ))
print(timeit.timeit('odd_even_filter_3([1, 2, 3, 4, 5, 6, 7, 8, 9])', setup="from __main__ import odd_even_filter_3" ))

>>2.2804439414858675
>>4.190625469924679
>>3.0541580641135733

0

基于ssm的帖子:

>>> l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> [list(filter(lambda x: x%2==0, l)), list(filter(lambda x: x%2==1, l))]
[[2, 4, 6, 8], [1, 3, 5, 7, 9]]

这个解决方案虽然可以,但速度较慢。


0

如果你的数字是连续的,你甚至可以使用切片:

>>> [r[1::2],r[2::2]]
[[1, 3, 5, 7, 9], [2, 4, 6, 8]]
>>>

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