tags:

views:

65

answers:

3

Hi, I'm looking for a "nice" way to process a list where some elements need to be expanded into more elements (only once, no expansion on the results).

Standard iterative way would be to do:

i=0
while i < len(l):
   if needs_expanding(l[i]):
      new_is = expand(l[i])
      l[i:i] = new_is
      i += len(new_is)
   else:
      i += 1

which is pretty ugly. I could rewrite the contents into a new list with:

nl = []
for x in l:
   if needs_expanding(x):
      nl += expand(x)
   else:
      nl.append(x)

But they both seem too long. Or I could simply do 2 passes and flatten the list later:

flatten(expand(x) if needs_expanding(x) else x for x in l)
# or
def try_expanding(x)....
flatten(try_expanding(x) for x in l)

but this doesn't feel "right" either.

Are there any other clear ways of doing this?

+2  A: 

The last one is probably your most pythonic, but you could try an implied loop (or in py3, generator) with map:

flatten(map(lambda x: expand(x) if needs_expanding(x) else x, l))
flatten(map(try_expanding, l))
Tor Valamo
+3  A: 

Your last two answers are what I would do. I'm not familiar with flatten() though, but if you have such a function then that looks ideal. You can also use the built-in sum():

sum(expand(x) if needs_expanding(x) else [x] for x in l, [])
sum(needs_expanding(x) and expand(x) or [x] for x in l, [])
John Kugelman
Ok - sum is pretty cool - didn't think of that one. Flatten is just some custom function to flatten the list - not in python (unfortunately).
viraptor
Unfortunately `sum()` has quadratic performance for lists
gnibbler
+2  A: 

If you do not need random access in the list you are generating, you could also use write a generator.

def iter_new_list(old_list):    
    for x in old_list:
       if needs_expanding(x):
           for y in expand(x):
               yield y
       else:
           yield x

new_list = list(iter_new_list(old_list))

This is functionally equivalent to your second example, but it might be more readable in your real-world situation.

Also, Python coding standards forbid the use of lowercase-L as a variable name, as it is nearly indistinguishable from the numeral one.

ddaa
re. lowercase-L - pylint keeps reminding me ;) I used it only to save typing in a trivial example...
viraptor