列表中的重复元素

22

我在Python中有一个列表:

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

我想立即复制每个原始元素旁边的元素。

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

元素的顺序应该被保留。


@Georgy 这与重复n次的问题相同。正如他们所说,“没有两个这样的东西”。https://en.wikipedia.org/wiki/Zero_one_infinity_rule - Karl Knechtel
6个回答

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']

或者

>>> from itertools import repeat
>>> [x for item in l for x in repeat(item, 2)]
['a', 'a', 'c', 'c', 'e', 'e', 'b', 'b']

1
作为一条注释,这对于可以被耗尽的任意可迭代对象是不起作用的。 - Gareth Latty
1
@Lattyware:没错,但它确实适用于所描述的问题。 - Steven Rumbalski
确实,这只是要记住的一些东西,以防有人试图在其他情况下应用它。 - Gareth Latty
@Lattyware:第二个版本中解决了的问题。 - Steven Rumbalski
是的,我唯一遇到的问题是多重循环列表推导式是将列表展平的相对低效的方法。在这种情况下,可能不太重要,但它也有点难以阅读。话虽如此,它并没有错,其他答案已经建议使用itertools.chain.from_iterable(),所以这没什么大不了的。 - Gareth Latty

17

这篇文章有些过时,但我认为没有直接的解决方案(在我看来):

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

因此,针对具体情况:

>>> 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']
>>> 

并且一般化:

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

其中r是您想要的重复次数。

因此,这个方法具有O(n.r)的时间和空间复杂度,简短明了,没有依赖关系,也很符合惯用法。


2
同样适用于Python 3,正是我所寻找的 :) - Bhaskar Kandiyal

7
import itertools

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

在工作中:

>>> 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']

正如Lattyware所指出的那样,如果您想要不止两倍的元素:
from itertools import chain, repeat

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

1
为了使其更加灵活,itertools.repeat()可能是一个更好的选择。 - Gareth Latty
1
我认为你想要使用chain.from_iterable - mgilson
很抱歉,我必须进行编辑以消除chain和其参数列表之间的空格。同时,按照mgilson的建议,使用了chain.from_iterable()进行修复。我还根据需要在参数之间添加了空格,并更改了通常用于表示丢弃值的下划线_ - Gareth Latty
@Lattyware,没关系。我对空格无能为力(我的工作编码标准,唉,很难改掉习惯)。但你刚好比我更早地使用了 from_iterable - StoryTeller - Unslander Monica
@StoryTeller 真的吗?那太糟糕了。这直接违反了 PEP-8 的建议,而我(个人认为)它非常丑陋。 - Gareth Latty
@Lattyware,我以C++为生,以Python为乐。所以情况更糟 :) 不过逗号后面的空格是打错了。 - StoryTeller - Unslander Monica

3

试试这个

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

演示

这只是完成工作的方法,但不是最优化的做法。

使用 @Steven Rumbalski 发布的答案。


这是一种相对低效的做法。 - Gareth Latty
@Lattyware 同意,但这个问题不值得更多。它没有提到需要优化的解决方案,只是想要一个解决方案。 - Arpit
这是一个疯狂的看法。更好的答案通常与此相似的代码量,并且在不需要额外努力的情况下,总是值得以最佳方式完成事情。 - Gareth Latty
好的,@Lattyware,下次我会记住这个。但现在我该怎么办呢?(解决方案已经给出,特斯拉本身知道答案。) - Arpit
我在哪里说过你需要对此做任何事情?这是一个有效的答案,我只是评论说它相对低效,并且没有点赞,因为它不是特别有用的解决方案。 - Gareth Latty
显示剩余4条评论

2
这里有一个非常简单的方法:
sum(zip(l, l), tuple())

这段代码会将每个项目复制一遍,并将它们添加到元组中。如果您不想使用元组(正如我所怀疑的那样),您可以对元组调用list

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

一些其他版本(生成列表):
list(sum(zip(l, l), ()))

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

sum(map(list, zip(l, l)), [])

1
这个可以运行,但它需要二次时间。这是一个非常糟糕的选择。 - user2357112

1

Pandas提供了一个关于重复元素的方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接