Python 带中断的列表理解
我有下面的代码,我想写在一行与列表理解Python 带中断的列表理解,python,list,list-comprehension,break,Python,List,List Comprehension,Break,我有下面的代码,我想写在一行与列表理解 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)
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]
3.6144596
8.731578200000001
我不知道该把它放在哪里
感谢您首先忽略中断条件有助于构建表达式:
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]]
从中可以添加最小约束:
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]
要构建表达式,首先忽略中断条件有助于:
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]]
从中可以添加最小约束:
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]
'''))
输出为:
[4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]
3.6144596
8.731578200000001
我试着给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]
'''))
输出为:
[4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]
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]
这比您原来的解决方案运行得稍慢,但是如果使用列表理解的目标是速度,那么您可以通过改进算法来获得更好的结果。例如,如果两个列表都已排序,则可以在跳过一次后立即丢弃列表2中的元素,而不是对照列表1的其余部分检查它们。您还可以对列表2进行二进制搜索,而不是线性扫描。您可以将中断逻辑移动到单独的函数中,然后将该函数放入列表中:
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]
这比您原来的解决方案运行得稍慢,但是如果使用列表理解的目标是速度,那么您可以通过改进算法来获得更好的结果。例如,如果两个列表都已排序,则可以在跳过一次后立即丢弃列表2中的元素,而不是对照列表1的其余部分检查它们。您还可以对列表2进行二进制搜索,而不是线性扫描。您无法真正中断列表理解的内部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 ]
输出:
print(list1)
print(list3)
[4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]
如果您担心性能,因为列表理解将比循环慢,您可以使用列表2中的对分搜索来查找下一个更高的值:
from bisect import bisect_left
list3 = [ list2[bisect_left(list2,i+1)] for i in list1 ]
这假设list2按升序排序,并且maxlist2>maxlist1您不能真正中断列表的内部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 ]
输出:
print(list1)
print(list3)
[4, 5, 6, 9, 10, 16, 21, 23, 25, 27]
[5, 7, 7, 11, 11, 17, 24, 24, 26, 56]
如果您担心性能,因为列表理解将比循环慢,您可以使用列表2中的对分搜索来查找下一个更高的值:
from bisect import bisect_left
list3 = [ list2[bisect_left(list2,i+1)] for i in list1 ]
这假设list2按升序排序,maxlist2>maxlist1