基于动态列表的for循环python
for loop based on dynamic list python
编辑:
该程序的预期行为是找到具有增加趋势的数字序列,因此我想从 ks
列表中生成一个这样的列表:
desiredList=[[97,122],[98,111],[98,101,103,103,104]]
我有以下内容,我的目标是 运行 基于列表长度的 for 循环,列表长度在 for 循环本身内部更改。 Python 只考虑 for 循环之前的长度,当循环中列表的长度发生变化时,它仍然采用循环之前的旧值。这是代码:
ks=[97,122,111,98,111,98,101,103,103,104,97]
splitLine=2
counter=[]
for i in range(0,len(ks)):
a=ks[i:splitLine]
while len(a)>1:
for j in range(0,len(a)):
m=j
n=j+1
if(a[m]-a[n]<=0):
c=c+1
k=splitLine+c-1
a.append(ks[k]) #When append happens, the for loop still takes the older value of len(a) instead of new value
else:
a.pop(-1)
counter.append(a)
splitLine=splitLine+1
a=[]
break
快速解决循环问题的方法是将 for
循环换成 while
循环。改变这个:
for j in range(0,len(a)):
# <loop contents>
对此:
j = 0
while j < len(a):
# <loop contents>
j += 1
for
循环从 range
中获取 j
的值(Python 2 中的 list
,Python 中的生成器对象 Python 3).这个range
是在for
循环第一次运行的时候计算的;之后它不会更新,无论你对 a
.
做什么
while
循环在这种情况下为您提供更多控制,因为您可以指定要退出循环的条件。
正如 Moinuddin 所说,我们不清楚您问题的根源。但是,下面的代码显示了如何在列表长度发生变化时对其进行迭代:
def iterate_for_static_list_length(l):
for i in range(len(l)):
yield i
l.append(object())
def iterate_for_dynamic_list_length(l):
for i, _ in enumerate(l):
yield i
l.append(object())
if __name__ == '__main__':
l = [object()] * 3
print('Static implementation')
for value in iterate_for_static_list_length(l):
input(value)
print('\nDynamic implementation')
for value in iterate_for_dynamic_list_length(l):
input(value)
输出
Static implementation
0
1
2
Dynamic implementation
0
1
2
3
4
5
6
7
8
该计划将永远进行下去。在您的代码中,我可以看到您 有条件地 附加到循环中的列表,因此它似乎最终应该终止。
您的实现可能为其试图解决的问题嵌套了太多循环。
第一个实现包含一个错误。请参阅下面的修复程序。
也许可以尝试以下方法:
l = [97,122,111,98,111,98,101,103,103,104,97]
out = []
acc = []
for v in l:
if len(acc)==0 or v >= acc[-1]:
acc.append(v)
else:
if len(acc) > 1:
out.append(acc)
acc = [v]
print(out)
>>>[[97, 122], [98, 111], [98, 101, 103, 103, 104]]
之前的代码很慢,可能会丢弃最后找到的片段。我在 运行 对其进行随机测试以尝试优化版本时发现了该错误。以下代码显示了经过更正的原始代码和可以提高 30% 速度的优化版本。
def original(l):
out = []
acc = []
added = False
for v in l:
if len(acc)==0 or v >= acc[-1]:
acc.append(v)
else:
added = False
acc = [v]
if acc is not None and len(acc)>1 and not added:
added = True
out.append(acc)
return out
def optimized(l):
out = []
acc = None
tmp = None
deb_v = False
for v in l:
prev = acc[-1] if (acc is not None and len(acc)) else tmp
if prev is not None and v >= prev:
if tmp is not None:
acc = []
acc.append(tmp)
out.append(acc)
tmp = None
acc.append(v)
else:
acc = None
tmp = v
return out
# The original test data
l = [97,122,111,98,111,98,101,103,103,104,97]
assert original(l) == optimized(l) == [[97,122],[98,111],[98,101,103,103,104]]
# A list that triggered last-fragment-dropped error
l = [57, 16, 6, 19, 40, 3, 4, 13, 2, 70, 85, 65, 32, 69, 54, 51, 95, 74, 92, 46, 45, 26, 0, 61, 99, 43, 67, 71, 97, 10, 18, 73, 88, 47, 33, 82, 25, 75, 93, 80, 23, 37, 87, 90, 49, 15, 35, 63, 17, 64, 5, 72, 89, 21, 50, 8, 41, 86, 31, 78, 52, 76, 56, 42, 77, 36, 11, 60, 39, 22, 68, 27, 24, 28, 59, 96, 29, 38, 12, 79, 53, 9, 83, 94, 34, 14, 7, 48, 30, 20, 66, 62, 91, 58, 81, 1, 98, 44, 55, 84]
assert original(l) == optimized(l)
# Random testing
import random
l = list(range(100))
random.shuffle(l)
assert original(l) == optimized(l)
# Timing!
import timeit
print(timeit.timeit("original(l)", globals={"l":l, "original": original}))
# 43.95869998800117
print(timeit.timeit("optimized(l)", globals={"l":l, "optimized": optimized}))
# 34.82134292599949
编辑:
该程序的预期行为是找到具有增加趋势的数字序列,因此我想从 ks
列表中生成一个这样的列表:
desiredList=[[97,122],[98,111],[98,101,103,103,104]]
我有以下内容,我的目标是 运行 基于列表长度的 for 循环,列表长度在 for 循环本身内部更改。 Python 只考虑 for 循环之前的长度,当循环中列表的长度发生变化时,它仍然采用循环之前的旧值。这是代码:
ks=[97,122,111,98,111,98,101,103,103,104,97]
splitLine=2
counter=[]
for i in range(0,len(ks)):
a=ks[i:splitLine]
while len(a)>1:
for j in range(0,len(a)):
m=j
n=j+1
if(a[m]-a[n]<=0):
c=c+1
k=splitLine+c-1
a.append(ks[k]) #When append happens, the for loop still takes the older value of len(a) instead of new value
else:
a.pop(-1)
counter.append(a)
splitLine=splitLine+1
a=[]
break
快速解决循环问题的方法是将 for
循环换成 while
循环。改变这个:
for j in range(0,len(a)):
# <loop contents>
对此:
j = 0
while j < len(a):
# <loop contents>
j += 1
for
循环从 range
中获取 j
的值(Python 2 中的 list
,Python 中的生成器对象 Python 3).这个range
是在for
循环第一次运行的时候计算的;之后它不会更新,无论你对 a
.
while
循环在这种情况下为您提供更多控制,因为您可以指定要退出循环的条件。
正如 Moinuddin 所说,我们不清楚您问题的根源。但是,下面的代码显示了如何在列表长度发生变化时对其进行迭代:
def iterate_for_static_list_length(l):
for i in range(len(l)):
yield i
l.append(object())
def iterate_for_dynamic_list_length(l):
for i, _ in enumerate(l):
yield i
l.append(object())
if __name__ == '__main__':
l = [object()] * 3
print('Static implementation')
for value in iterate_for_static_list_length(l):
input(value)
print('\nDynamic implementation')
for value in iterate_for_dynamic_list_length(l):
input(value)
输出
Static implementation
0
1
2
Dynamic implementation
0
1
2
3
4
5
6
7
8
该计划将永远进行下去。在您的代码中,我可以看到您 有条件地 附加到循环中的列表,因此它似乎最终应该终止。
您的实现可能为其试图解决的问题嵌套了太多循环。
第一个实现包含一个错误。请参阅下面的修复程序。
也许可以尝试以下方法:
l = [97,122,111,98,111,98,101,103,103,104,97]
out = []
acc = []
for v in l:
if len(acc)==0 or v >= acc[-1]:
acc.append(v)
else:
if len(acc) > 1:
out.append(acc)
acc = [v]
print(out)
>>>[[97, 122], [98, 111], [98, 101, 103, 103, 104]]
之前的代码很慢,可能会丢弃最后找到的片段。我在 运行 对其进行随机测试以尝试优化版本时发现了该错误。以下代码显示了经过更正的原始代码和可以提高 30% 速度的优化版本。
def original(l):
out = []
acc = []
added = False
for v in l:
if len(acc)==0 or v >= acc[-1]:
acc.append(v)
else:
added = False
acc = [v]
if acc is not None and len(acc)>1 and not added:
added = True
out.append(acc)
return out
def optimized(l):
out = []
acc = None
tmp = None
deb_v = False
for v in l:
prev = acc[-1] if (acc is not None and len(acc)) else tmp
if prev is not None and v >= prev:
if tmp is not None:
acc = []
acc.append(tmp)
out.append(acc)
tmp = None
acc.append(v)
else:
acc = None
tmp = v
return out
# The original test data
l = [97,122,111,98,111,98,101,103,103,104,97]
assert original(l) == optimized(l) == [[97,122],[98,111],[98,101,103,103,104]]
# A list that triggered last-fragment-dropped error
l = [57, 16, 6, 19, 40, 3, 4, 13, 2, 70, 85, 65, 32, 69, 54, 51, 95, 74, 92, 46, 45, 26, 0, 61, 99, 43, 67, 71, 97, 10, 18, 73, 88, 47, 33, 82, 25, 75, 93, 80, 23, 37, 87, 90, 49, 15, 35, 63, 17, 64, 5, 72, 89, 21, 50, 8, 41, 86, 31, 78, 52, 76, 56, 42, 77, 36, 11, 60, 39, 22, 68, 27, 24, 28, 59, 96, 29, 38, 12, 79, 53, 9, 83, 94, 34, 14, 7, 48, 30, 20, 66, 62, 91, 58, 81, 1, 98, 44, 55, 84]
assert original(l) == optimized(l)
# Random testing
import random
l = list(range(100))
random.shuffle(l)
assert original(l) == optimized(l)
# Timing!
import timeit
print(timeit.timeit("original(l)", globals={"l":l, "original": original}))
# 43.95869998800117
print(timeit.timeit("optimized(l)", globals={"l":l, "optimized": optimized}))
# 34.82134292599949