2017-01-19 44 views
1

編輯: 該方案的期望的行爲是要找到有增加的趨勢的數字序列,所以我想從ks列表生成像這樣的列表: desiredList=[[97,122],[98,111],[98,101,103,103,104]]for循環基於動態列表蟒蛇

我有以下幾點,我的目標是根據列表長度運行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 
+3

您解釋了'for'循環的行爲。但你試圖解決的問題陳述並不清楚。請編輯問題以解釋所需的行爲。另外提及樣本輸入和期望的輸出 –

+1

您的代碼中除了您聲明的代碼之外的幾個問題。 'a [m]'和'a [n]'是字符串,你在哪裏首先定義'c'? – Tagc

+1

你想做什麼?迭代時修改列表幾乎總是一個壞主意 –

回答

1

您的實現可能會爲它正在嘗試解決的問題嵌套太多的循環。

該第一個實現包含錯誤。請參閱下面的修復。

嘗試一些沿也許這些線路:

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 
0

要快速解決您的問題,循環將換出你的for循環的while循環。改變這一:

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

這樣:

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

for環斂的值jrange的(在Python 2 list,和在Python 3的發電機對象)。當for循環第一次運行時計算range;它不會更新後,無論你做什麼a

在這種情況下,while循環使您可以更好地控制,因爲您可以指定要退出循環的條件。

0

正如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 

這項計劃將繼續下去,直到永遠。在你的代碼中,我可以看到你有條件地追加到循環內的列表,所以它似乎應該終止。