Reputation: 11677
Similar to this question, but instead of replacing one item with another, I'd like to replace any occurrences of one item with the contents of a list.
orig = [ 'a', 'b', 'c', 'd', 'c' ]
repl = [ 'x', 'y', 'z' ]
desired = [ 'a', 'b', 'x', 'y', 'z', 'd', 'x', 'y', 'z' ]
# these are all incorrect, or fail to compile
[ repl if x == 'c' else x for x in orig ]
[ [a for a in orig] if x == 'c' else x for x in orig ]
[ (a for a in orig) if x == 'c' else x for x in orig ]
[ a for a in orig if x == 'c' else x for x in orig ]
Edit: made it clear I meant to replace all occurrences of the item, rather than just the first. (Apologies to anyone who didn't cover that case in their answer.)
Upvotes: 2
Views: 5959
Reputation: 3704
Yet another way:
>>> import operator
>>> orig = [ 'a', 'b', 'c', 'd', 'c' ]
>>> repl = [ 'x', 'y', 'z' ]
>>> output = [repl if x == 'c' else [x] for x in orig]
>>> reduce(operator.add, output)
['a', 'b', 'x', 'y', 'z', 'd', 'x', 'y', 'z']
>>>
Upvotes: 0
Reputation: 77347
If you enumerate backwards, you can extend the list as you go because the items you move have already gone through the enumeration.
>>> orig = [ 'a', 'b', 'c', 'd', 'c' ]
>>> repl = [ 'x', 'y', 'z' ]
>>> desired = [ 'a', 'b', 'x', 'y', 'z', 'd', 'x', 'y', 'z' ]
>>> for i in xrange(len(orig)-1, -1, -1):
... if orig[i] == 'c':
... orig[i:i+1] = repl
...
>>> orig
['a', 'b', 'x', 'y', 'z', 'd', 'x', 'y', 'z']
Upvotes: 0
Reputation: 353059
Different approach: when I'm doing replacements, I prefer to think in terms of dictionaries. So I'd do something like
>>> orig = [ 'a', 'b', 'c', 'd' ]
>>> rep = {'c': ['x', 'y', 'z']}
>>> [i for c in orig for i in rep.get(c, [c])]
['a', 'b', 'x', 'y', 'z', 'd']
where the last line is the standard flattening idiom.
One advantage (disadvantage?) of this approach is that it'll handle multiple occurrences of 'c'
.
[update:]
Or, if you prefer:
>>> from itertools import chain
>>> list(chain.from_iterable(rep.get(c, [c]) for c in orig))
['a', 'b', 'x', 'y', 'z', 'd']
On the revised test case:
>>> orig = [ 'a', 'b', 'c', 'd', 'c' ]
>>> rep = {'c': ['x', 'y', 'z']}
>>> list(chain.from_iterable(rep.get(c, [c]) for c in orig))
['a', 'b', 'x', 'y', 'z', 'd', 'x', 'y', 'z']
Upvotes: 4
Reputation: 309929
>>> orig = [ 'a', 'b', 'c', 'd' ]
>>> repl = [ 'x', 'y', 'z' ]
>>> desired = list(orig) #can skip this and just use `orig` if you don't mind modifying it (and it is a list already)
>>> desired[2:3] = repl
>>> desired
['a', 'b', 'x', 'y', 'z', 'd']
And of course, if you don't know that 'c'
is at index 2, you can use orig.index('c')
to find out that information.
Upvotes: 6
Reputation: 33397
No need for anything fancy:
desired = orig[:2] + repl + orig[3:]
To find 2
you can search for orig.index('c')
.
x = orig.index('c')
desired = orig[:x] + repl + orig[x+1:]
if repl is not a list, just use list(repl)
Upvotes: 2