简体   繁体   English

基于动态列表python的for循环

[英]for loop based on dynamic list python

Edit: The desired behaviour of the program is to find the number sequences that have an increasing trend, so I want to generate from ks list a list like this: desiredList=[[97,122],[98,111],[98,101,103,103,104]]编辑:程序的期望行为是找到具有增加趋势的数字序列,所以我想从ks列表中生成一个这样的列表: desiredList=[[97,122],[98,111],[98,101,103,103,104]]

I have the following, my goal is to run the for loop based on the length of the list, the list length gets changed inside the for loop itself.我有以下内容,我的目标是根据列表的长度运行 for 循环,列表长度在 for 循环本身内部发生变化。 Python takes into account only the length before the for loop, when the length of the list is changed in the loop it still takes the older value before the loop. Python 只考虑 for 循环之前的长度,当列表的长度在循环中改变时,它仍然采用循环之前的旧值。 Here is the code:这是代码:

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

A quick fix for your looping problem would be to swap out your for loop for a while loop.快速解决循环问题的方法是将for循环换成while循环。 Change this:改变这个:

for j in range(0,len(a)):
    # <loop contents>

to this:对此:

j = 0
while j < len(a):
    # <loop contents>
    j += 1

The for loop is grabbing values of j out of a range (a list in Python 2, and a generator object in Python 3). for循环从一个range (Python 2 中的list和 Python 3 中的生成器对象)中获取j值。 This range is calculated when the for loop is run the first time;这个range是在第一次运行for循环时计算的; it will not update after that, no matter what you do to a .之后,它不会更新,不管你做什么a

The while loop gives you more control in this situation, because you can specify the condition under which you want to exit the loop.在这种情况下, while循环为您提供了更多控制权,因为您可以指定退出循环的条件。

Your implementation is probably nesting too many loops for the problem it is trying to solve.您的实现可能为它试图解决的问题嵌套了太多循环。

This first implementation contains an error.第一个实现包含一个错误。 See below for the fix.请参阅下面的修复程序。

Try something along these lines perhaps:尝试以下方法:

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]]

That previous code is slow and can drop the last found fragment .以前的代码很慢,并且可以删除最后找到的片段 I found that error while running random tests on it to try an optimized version.我在对其运行随机测试以尝试优化版本时发现了该错误。 The following code shows the original code with the correction and the optimized version which can be 30% faster.以下代码显示了经过更正的原始代码和可以提高 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

As Moinuddin says, the root of your problem isn't clear to us.正如 Moinuddin 所说,我们不清楚您问题的根源。 However, the code below shows how you can keep iterating over a list as its length changes:但是,下面的代码显示了如何在列表长度变化时继续迭代它:

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)

Output输出

Static implementation
0
1
2

Dynamic implementation
0
1
2
3
4
5
6
7
8

This program will keep going forever.这个程序将永远持续下去。 In your code I can see that you conditionally append to the list within the loop, so it seems like it should terminate eventually.在您的代码中,我可以看到您有条件地附加到循环内的列表中,因此它似乎最终应该终止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM