python - What's an elegant way for one loop iteration to affect another? -
i needed process config file now. because of way generated, contains lines this:
---(more 15%)---   the first step strip these unwanted lines out. slight twist, each of these lines followed blank line, want strip. created quick python script this:
skip_next = false line in sys.stdin:     if skip_next:         skip_next = false         continue         if line.startswith('---(more'):         skip_next = true         continue         print line,   now, works, it's more hacky i'd hoped. difficulty when looping through lines, want content of 1 line affect subsequent line. hence question: what's elegant way 1 loop iteration affect another?
another way itertools.tee, allows split iterator two.  can advance 1 iterator 1 step, putting 1 iterator 1 line ahead of other.  can zip 2 iterators , @ both previous line , current line @ each step of for loop (i use izip_longest doesn't drop last line):
from itertools import tee, izip_longest in1, in2 = tee(sys.stdin, 2) next(in2) line, prevline in izip_longest(in1, in2, fillvalue=''):     if line.startswith('---(more') or prevline.startswith('---(more'):         continue     print line   this done equivalent generator expression:
from itertools import tee, izip_longest in1, in2 = tee(sys.stdin, 2) next(in2) pairs = izip_longest(in1, in2, fillvalue='') res = (line line, prevline in pairs        if not line.startswith('---(more') , not prevline.startswith('---(more')) line in res:     print line   or use filter, allows drop iterator items when condition not true.
from itertools import tee, izip_longest in1, in2 = tee(sys.stdin, 2) next(in2) pairs = izip_longest(in1, in2, fillvalue='') cond = lambda pair: not pair[0].startswith('---(more') , not pair[1].startswith('---(more') res = filter(cond, pairs) line in res:     print line   if willing go outside python standard library, toolz package makes easier.  provides sliding_window function, allows split iterator such a b c d e f (a,b), (b,c), (c,d), (d,e), (e,f).  same thing tee approach above, combined 3 lines one:
from toolz.itertoolz import sliding_window line, prevline in sliding_wind(2, sys.stdin):     if line.startswith('---(more') or prevline.startswith('---(more'):         continue     print line   you additionally use remove, opposite of filter, drop items without needing for loop:
from tools.itertoolz import sliding_window, remove pairs = sliding_window(2, sys.stdin) cond = lambda x: x[0].startswith('---(more') or x[1].startswith('---(more') res = remove(cond, pairs) line in res:     print line      
Comments
Post a Comment