2016-09-29 7 views
0

のサイズがの場合、コードのこの部分が縮尺されません。ループするときにリストから要素を削除する

私はデータをループして、毎回dt時間窓ごとに累積します。これを行うために、私は下限値と上限値を比較します。上限に達すると、効率的にループのためにを破ります。次回、私がループのためにを走らせるとき、私はその最初からではなく、効率のために私が以前に止めた要素から始めたいと思う。 どうすればいいですか?

リストの要素を削除/ポップしようとしましたが、インデックスがうまくいきません。私はリストを修正することはできませんが、私はループしていますが、私の目標は稀ではないようですので、解決策が必要です。私はオリジナルのデータリストについては後で私のコードで気にしません、私は自分の蓄積の最適化が欲しいだけです。

簡単な形で
# Here I generate data for you to show my problem 
from random import randint 
import numpy as np 

dimension = 200 
times = [randint(0, 1000) for p in range(0, dimension)] 
times.sort() 
values = [randint(0, dimension) for p in range(0, dimension)] 
data = [(values[k], times[k]) for k in range(dimension)] 
dt = 50.0 
t = min(times) 
pixels = [] 
timestamps = [] 

# this is my problem 
while (t <= max(times)): 
    accumulator = np.zeros(dimension) 
    for idx, content in enumerate(data): 
     # comparing lower bound of the 'time' window 
     if content[1] >= t: 
      # comparing upper bound of the 'time' window 
      if (content[1] < t + dt): 
       accumulator[content[0]] += 1 
       # if I pop the first element from the list after accumulating, indexes are screwed when looping further 
       # data.pop(0) 
      else: 
       # all further entries are bigger because they are sorted 
       break 

    pixels.append(accumulator) 
    timestamps.append(t) 
    t += dt 
+0

forループを独自の関数に分割すると、ループの開始インデックスをパラメータとして渡すことができます([range()](https://docs.python.org/2/library) /functions.html#range)をループ内に追加します)。その後、ループを再開すると、終了した索引からループを呼び出すことができます。最初に関数を呼び出してゼロを渡します。このパラメータは、rangeと呼ぶ最初のパラメータにもなります。 –

+4

要素を削除する場合は、後ろにループしたり、リストのコピーを作成したり、リストの理解を使用したりできます。 [this](http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python) –

+0

ありがとう!私はrange()が私の心に来なかったので、もっとPythonの練習が必要です。私はC++の反復子を見つけようとしていました。 – beginh

答えて

0

、私はあなたがやろうとしていると思う:

In [158]: times=[0, 4, 6, 10] 
In [159]: data=np.arange(12) 
In [160]: cnt=[0 for _ in times] 
In [161]: for i in range(len(times)-1): 
    ...:  for d in data: 
    ...:   if d>=times[i] and d<times[i+1]: 
    ...:    cnt[i]+=1 
    ...:    
In [162]: cnt 
Out[162]: [4, 2, 4, 0] 

そして、あなたはdが大きくなりすぎたときにループを形成して破壊することによって、このdataループをより効率的にしようとしている、とすでに数えられているアイテムの次のループを開始することによって実行される。あなたがやったよう

休憩を追加するのは簡単です:数えものをスキップする

In [163]: cnt=[0 for _ in times] 
In [164]: for i in range(len(times)-1): 
    ...:  for d in data: 
    ...:   if d>=times[i]: 
    ...:    if d<times[i+1]: 
    ...:     cnt[i]+=1 
    ...:    else: 
    ...:     break 

In [165]: cnt 
Out[165]: [4, 2, 4, 0] 

一つの方法は、インデックスループとfor d in dataを交換することです。そして私たちは周りの最後の時間を停止した場所を追跡:

In [166]: cnt=[0 for _ in times] 
In [167]: start=0 
    ...: for i in range(len(times)-1): 
    ...:  for j in range(start,len(data)): 
    ...:   d = data[j] 
    ...:   if d>=times[i]: 
    ...:    if d<times[i+1]: 
    ...:     cnt[i]+=1 
    ...:    else: 
    ...:     start = j 
    ...:     break 
    ...:     
In [168]: cnt 
Out[168]: [4, 2, 4, 0] 

popベースのバージョンは、私は(私のdataが配列である)リストで作業する必要があり、休憩

In [186]: datal=data.tolist() 
In [187]: cnt=[0 for _ in times] 
In [188]: for i in range(len(times)-1): 
    ...:  while True: 
    ...:   d = datal.pop(0) 
    ...:   if d>=times[i]: 
    ...:    if d<times[i+1]: 
    ...:     cnt[i]+=1 
    ...:    else: 
    ...:     datal.insert(0,d) 
    ...:     break 
    ...:    
In [189]: cnt 
Out[189]: [4, 2, 4, 0] 
In [190]: datal 
Out[190]: [10, 11] 
に戻って値を挿入する必要があり

最後にリストに項目が残っているため、これは完璧ではありません(timesdataの範囲全体をカバーしていません)。しかし、それはアイデアをテストします。主な違いは、私はdatalのコピーに繰り返すことである

In [203]: for i in range(len(times)-1): 
    ...:  for d in datal[:]: 
    ...:   if d>=times[i]: 
    ...:    if d<times[i+1]: 
    ...:     cnt[i]+=1 
    ...:     datal.pop(0) 
    ...:    else: 
    ...:     break 
    ...:  

:ここ

はあなたの試みに近い何か。そうすればpopdatalに影響しますが、現在の反復には影響しません。間違いなくコピーにはコストがかかるため、スピードアップが重要になる可能性があります。

異なるアプローチは、dataをループすることであり、tt+dtの境界として、timeを交差させることです。

関連する問題