Say I have a Python list like this:
letters = [\'a\',\'b\',\'c\',\'d\',\'e\',\'f\',\'g\',\'h\',\'i\',\'j\']
I want to insert an \'x\' after
A pretty straightforward method:
>>> letters = ['a','b','c','d','e','f','g','h','i','j']
>>> new_list = []
>>> n = 3
>>> for start_index in range(0, len(letters), n):
... new_list.extend(letters[start_index:start_index+n])
... new_list.append('x')
...
>>> new_list.pop()
'x'
>>> new_list
['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']
You can also use the grouper
recipe from the itertools documentation for the chunking.
I've got two one liners.
Given:
>>> letters = ['a','b','c','d','e','f','g','h','i','j']
Use enumerate
to get index, add 'x'
every 3rd letter, eg: mod(n, 3) == 2
, then concatenate into string and list()
it.
>>> list(''.join(l + 'x' * (n % 3 == 2) for n, l in enumerate(letters)))
['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']
But as @sancho.s points out this doesn't work if any of the elements have more than one letter.
Use nested comprehensions to flatten a list of lists(a), sliced in groups of 3 with 'x'
added if less than 3 from end of list.
>>> [x for y in (letters[i:i+3] + ['x'] * (i < len(letters) - 2) for
i in xrange(0, len(letters), 3)) for x in y]
['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']
(a) [item for subgroup in groups for item in subgroup]
flattens a jagged list of lists.
It's worth stating the simple implementation too:
letters = ['a','b','c','d','e','f','g','h','i','j']
i = 3 #initial step
while i < len(letters):
letters.insert(i,'x')
i = i + 3 + 1 #increment step by one for every loop to account for the added element
It does use basic looping and inserting, but it also looks much simpler and comfortable to read than the one-liner examples, which IMHO makes it more Pythonish as requested in the first place.
I want to add a new element per item.
How about this ?
a=[2,4,6]
for b in range (0,len(a)):
a.insert(b*2,1)
a is now
[1, 2, 1, 4, 1, 6]
Although using list.insert()
in a for
loop seems to be more memory efficient, in order to do it in one-line, you can also append the given value at the end of every equally divided chunks split on every nth
index of the list.
>>> from itertools import chain
>>> n = 2
>>> ele = 'x'
>>> lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> list(chain(*[lst[i:i+n] + [ele] if len(lst[i:i+n]) == n else lst[i:i+n] for i in xrange(0, len(lst), n)]))
[0, 1, 'x', 2, 3, 'x', 4, 5, 'x', 6, 7, 'x', 8, 9, 'x', 10]
This is an old topic, but it lacks the easiest, most "pythonic" solution, imo. It is no more than an extension to part 2 of Mark Mikofski's accepted answer that arguably improves readability (and therefore makes it more pythonic).
>>> letters = ['a','b','c','d','e','f','g','h','i','j']
>>> [el for y in [[el, 'x'] if idx % 3 == 2 else el for
idx, el in enumerate(letters)] for el in y]
['a', 'b', 'c', 'x', 'd', 'e', 'f', 'x', 'g', 'h', 'i', 'x', 'j']