我有下面的代码,我想用列表理解法一行行写出来。
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语句放在哪里才好
谢谢你的帮助
你不能真正打破列表理解的内部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)
构建表达式时,可以忽略 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]
我试着按照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
你可以把中断逻辑移到一个单独的函数中 然后把这个函数放在一个列表理解里面
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进行二进制搜索,而不是线性地扫描一遍。