Python 从列表中删除特定重复项

3

我想从一个列表中删除特定的重复项。如果使用Perl,我会使用以下代码来完成这个任务:

my @list = ( 'a1', 'a1', 'b1', 'b1' );

my %seen;
@list = grep( !/a\d/ || !$seen{ $_ }++, @list );

期望的结果应该是这样的:

@list = ( 'a1', 'b1', 'b1' );

我该如何使用正则表达式和列表推导在Python 3中完成这个操作?谢谢。

1
我不会说 Perl。当重复项匹配正则表达式 /a\d/ 时,该代码是否会删除重复项,但否则呢? - senshin
是的。该代码仅删除与正则表达式 /a\d/ 匹配的重复项。 - theuserid01
3个回答

1
你可以使用 itertools.chaingroupby
>>> list(chain(*[[i[0]] if 'a1' in i else i for i in [list(g) for _,g in groupby(sorted(l))]]))
['a1', 'b1', 'b1']

如果您只想使用正则表达式,可以连接元素,然后使用re.sub,但请注意,它仅适用于这种特殊情况!即是分隔符!:

>>> l =['a1', 'a1', 'b1', 'b1']
>>> re.sub(r'(a1,)+','a1,',','.join(sorted(l))).split(',')
['a1', 'b1', 'b1']

2
我不确定你是否理解了OP所说的“使用正则表达式”的意思。无论如何,你的正则表达式解决方案非常脆弱(如果在一个或多个元素内部有逗号怎么办?),并且不能保证保留元素的原始顺序,这可能很重要。 - John Y
@JohnY 是的,我只是为了这个案例添加了它,但无论如何我需要将此点添加到答案中! - Mazdak

1
import re
from functools import reduce  # this import is not needed in python 2.*

l = ['a1', 'a1', 'b1', 'b1']

print reduce(lambda acc, el: acc if re.match(r'a\d', el) and el in acc else acc + [el], l, [])

抱歉,这个解决方案没有使用列表推导式。这是严格要求的吗?


不需要使用列表推导式。我正在寻找一行代码的解决方案,你的代码完美地符合了我的要求。谢谢。 - theuserid01

0
这是另一种解决方案,使用 list(set(stuff))stuff 中生成一个独特事物的列表(因为set自动去重)。
In [1]: import re

In [2]: l = ["a1", "a1", "b1", "b1"]

In [3]: items_to_dedupe = [x for x in l if re.match(r"a\d", x)]

In [4]: leave_alone = [x for x in l if x not in items_to_dedupe]

In [5]: list(set(items_to_dedupe)) + leave_alone
Out[5]: ['a1', 'b1', 'b1']

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