列表理解

问题描述 投票:0回答:1

我有下面的代码,我想用列表理解法一行行写出来。

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]

list3 = []
for i in list1:
    for j in list2:
        if j>i:
            # print(i,j)
            list3.append(j)
            break
print(list1)
print(list3)

输出的是。

[4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]

我不知道该把break语句放在哪里才好

谢谢你的帮助

python list list-comprehension break
1个回答
1
投票

你不能真正打破列表理解的内部for循环,你能做的是通过使用next函数找到匹配值的第一次出现,从而完全避免不得不打破它。

list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56]
list3 = [ next(j for j in list2 if j>i) for i in list1 ]

output。

print(list1)
print(list3)
[4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]

如果你担心性能问题(因为list comprehension会比循环慢),你可以在list2中使用二分搜索来寻找下一个更高的值。

from bisect import bisect_left
list3 = [ list2[bisect_left(list2,i+1)] for i in list1 ]

这假定list2是按升序排列的,并且max(list2) > max(list1)


2
投票

构建表达式时,可以忽略 break 的条件。

In [32]: [[j for j in list2 if j > i] for i in list1]                                       
Out[32]: 
[[5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56],
 [7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56],
 [7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 56],
 [11, 12, 13, 14, 15, 17, 20, 24, 26, 56],
 [11, 12, 13, 14, 15, 17, 20, 24, 26, 56],
 [17, 20, 24, 26, 56],
 [24, 26, 56],
 [24, 26, 56],
 [26, 56],
 [56]]

从那里你可以添加 min 的约束。

In [33]: [min([j for j in list2 if j > i]) for i in list1]                                  
Out[33]: [5, 7, 7, 11, 11, 17, 24, 24, 26, 56]

0
投票

我试着按照AbbeGijly的答案计时。

结果发现比原来的解法慢了。看看吧。

import timeit

print(timeit.timeit('''
list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 40, 56]

list3 = []
for i in list1:
    for j in list2:
        if j>i:
            # print(i,j)
            list3.append(j)
            break
'''))

print(timeit.timeit('''
list1 = [4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
list2 = [1, 3, 5, 7, 8, 11, 12, 13, 14, 15, 17, 20, 24, 26, 40, 56]
list4 = [[j for j in list2 if j > i] for i in list1]
'''))

输出的是。

3.6144596
8.731578200000001

0
投票

你可以把中断逻辑移到一个单独的函数中 然后把这个函数放在一个列表理解里面

def smallest_value_larger_than_i(candidate_values, i):
    for value in candidate_values:
        if value > i:
            return value
    return None  # Not sure how you want to handle this case

list3 = [smallest_value_larger_than_i(list2, i) for i in list1]

这比原来的方案运行速度稍慢 但如果使用列表理解法的目的是为了速度 你可以通过改进算法来获得更好的结果 例如,如果两个列表都是排序的,那么你只要跳过一次list2中的元素,就可以将它们丢弃,而不是对照list1的其他元素进行检查。你也可以对list2进行二进制搜索,而不是线性地扫描一遍。

© www.soinside.com 2019 - 2024. All rights reserved.