22

I have a list in Python:

l = ['a', 'c', 'e', 'b']

I want to duplicate each element immediately next to the original.

ll = ['a', 'a', 'c', 'c', 'e', 'e', 'b', 'b']

The order of the elements should be preserved.

Georgy
  • 12,464
  • 7
  • 65
  • 73
tesla1060
  • 2,621
  • 6
  • 31
  • 43
  • 1
    Related questions: [Repeating elements of a list n times](https://stackoverflow.com/q/24225072/7851470), [Best way to extend a list with itself N times](https://stackoverflow.com/q/46560385/7851470). – Georgy Oct 01 '19 at 20:51
  • @Georgy this is the same as the repeating-n-times question. "There's no such thing as two", as they say. https://en.wikipedia.org/wiki/Zero_one_infinity_rule – Karl Knechtel Aug 13 '22 at 08:27

6 Answers6

25
>>> l = ['a', 'c', 'e', 'b']
>>> [x for pair in zip(l,l) for x in pair]
['a', 'a', 'c', 'c', 'e', 'e', 'b', 'b']

Or

>>> from itertools import repeat
>>> [x for item in l for x in repeat(item, 2)]
['a', 'a', 'c', 'c', 'e', 'e', 'b', 'b']
Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
17

This is old but I can't see the straightforward option here (IMO):

[ item for item in l for repetitions in range(2) ]

So for the specific case:

>>> l = ['a', 'c', 'e', 'b']
l = ['a', 'c', 'e', 'b']
>>> [ i for i in l for r in range(2) ]
[ i for i in l for r in range(2) ]
['a', 'a', 'c', 'c', 'e', 'e', 'b', 'b']
>>> 

And generalizing:

[ item for item in l for _ in range(r) ] 

Where r is the quantity of repetitions you want.

So this has a O(n.r) space and time complexity, is short, with no dependencies and also idiomatic.

olivecoder
  • 2,858
  • 23
  • 22
7
import itertools

ll = list(itertools.chain.from_iterable((e, e) for e in l))

At work:

>>> import itertools
>>> l = ['a', 'c', 'e', 'b']
>>> ll = list(itertools.chain.from_iterable((e, e) for e in l))
>>> ll
['a', 'a', 'c', 'c', 'e', 'e', 'b', 'b']

As Lattyware pointed out, in case you want more than just double the element:

from itertools import chain, repeat

ll = list(chain.from_iterable(repeat(e, 2) for e in l))
Gareth Latty
  • 86,389
  • 17
  • 178
  • 183
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    To make this a little more flexible `itertools.repeat()` might be a better option. – Gareth Latty Feb 14 '13 at 15:47
  • 1
    I think you wanted `chain.from_iterable` – mgilson Feb 14 '13 at 15:49
  • I'm sorry, but I had to edit to get rid of that space between `chain` and it's argument list. Also, fixed by using `chain.from_iterable()` as mgilson suggested. I also added spaces between arguments as appropriate, and changed `_` - which is usually used to signify a throw away value. – Gareth Latty Feb 14 '13 at 15:50
  • @Lattyware, it's OK. I can't do anything about the spaces (coding standards at my job, yeesh. Hard to kick the habbit). But you just beat me to the `from_iterable` – StoryTeller - Unslander Monica Feb 14 '13 at 15:52
  • @StoryTeller Really? That sucks. It's directly against what PEP-8 recommends, and I (personally) think it's ugly as hell. – Gareth Latty Feb 14 '13 at 15:52
  • @Lattyware, I code in C++ for a living and python for fun. So it's even worse :) The spaces after the commas are a typo, though. – StoryTeller - Unslander Monica Feb 14 '13 at 15:54
3

Try this

for i in l:
    ll.append(i)
    ll.append(i)

Demo

It will just do your work but it's not an optimized way of doing this.

use the ans. posted by @Steven Rumbalski

Arpit
  • 12,767
  • 3
  • 27
  • 40
  • This is a relatively inefficient way of doing this. – Gareth Latty Feb 14 '13 at 15:56
  • @Lattyware Agree but this Ques. doesn't deserve more than this.it is not mentioned that it require an optimized solution.it just want a solution. – Arpit Feb 14 '13 at 16:00
  • That's a crazy way to look at it. The better answers are generally similar amounts of code to this, and it's always worth doing things the best way possible where it doesn't take extra effort to do so. – Gareth Latty Feb 14 '13 at 16:05
  • Ok @Lattyware next time i will remember this. but what can i do now.(The solution is already given and tesla itself know the ans.) – Arpit Feb 14 '13 at 16:18
  • Where did I say that you needed to do anything about it? It's a valid solution to the answer, I'm just commented that it was relatively inefficient, and didn't upvote because it isn't a particularly useful solution. – Gareth Latty Feb 14 '13 at 16:22
  • @Lattyware Oh! thanks for pointing this. next time i will take care of this. :) – Arpit Feb 14 '13 at 16:24
  • @Arpit this man deserves a golden medal. It works without any complications and that's all it matters. – user1241241 Jun 12 '20 at 12:59
  • @GarethLatty it is a useful solution for me even during 2020 – user1241241 Jun 12 '20 at 12:59
  • @GarethLatty and I'm upvoting this – user1241241 Jun 12 '20 at 12:59
2

Here's a pretty easy way:

sum(zip(l, l), tuple())

It duplicates each item, and adds them to a tuple. If you don't want a tuple (as I suspect), you can call list on the the tuple:

list(sum(zip(l, l), tuple()))

A few other versions (that yield lists):

list(sum(zip(l, l), ()))

sum([list(i) for i in zip(l, l)], [])

sum(map(list, zip(l, l)), [])
Zach Gates
  • 4,045
  • 1
  • 27
  • 51
1

Pandas gives a method for duplicated elements:

import pandas as pd
l = pd.Series([2, 1, 3, 1])
print(l.duplicated())
>>>0    False
   1    False
   2    False
   3     True
   dtype: bool

print('Has list duplicated ? :', any(l.duplicated()))
>>>Has list duplicated ? : True
Valentin Fabianski
  • 646
  • 1
  • 5
  • 12