Python列表交集包含非唯一项

13

我有两个字符串,我想在它们之间找到交集,并且这些交集中包含重复项:

str_a = "aabbcc"
str_b = "aabd"

list(set(str_a) & set(str_b))
>> "ab"

我希望它返回:

>> "aab"

有什么想法吗?


2
为什么选择"aab"而不是"aaaabbb""aabb" - Marcin
3
因为这是我想要的。功能性问题是:给我所有可以由给定字母输入(str_b)构建而成的单词(str_a)。 - RickyA
1
没错,但你应用了什么规则使得那是正确的答案呢?如果你只想操作这两个特定的字符串,你可以将其硬编码到一个if语句中。 - Marcin
是的,但显然这只是我真正想做的简化版本。如果我的问题可以用几行代码展示出来,那么让人们阅读大量代码就没有意义了... - RickyA
1
这仍然没有告诉我们这里应该是什么规则。在您告诉我们之前,这个问题是未指定的。恰好有一个Python库可以正确执行此操作,这很棒,但是这个问题仍然是未指定的。 - Marcin
2个回答

19

在Python 2.7或更高版本中,多重集合被实现为(可变的)Counter对象。您可以执行与集合相同的许多操作,例如并集、交集、差集(虽然计数可能变为负数)等:

多重集合是指允许有重复元素的集合。相比之下,普通集合不允许有重复元素。使用Counter对象,您可以轻松地对多重集合进行计数和操作。

from collections import Counter as mset

解决方案:

(mset("aabbcc") & mset("aabd")).elements()

更多细节:

>>> intersection = mset("aabbcc") & mset("aabd")
Counter({'a': 2, 'b': 1})

>>> list(intersection.elements())
['a', 'a', 'b']

>>> ''.join(intersection.elements())
'aab'
你可以使用''.join来获取字符串,或者使用list()获取列表。但是,如果我只想保持可迭代格式,那么我会使用intersection.elements()

这完全不是他要求的。他想要字符串的交集 - BrenBarn
这是元素的并集,而不是交集。 - Blckknght
这甚至不是联合,而是多重集合和(例如联合仅包含两个“a”)。 - BrenBarn
2
@ninjagecko:不太对,你的“intersection”输出是错误的,而且也很令人困惑。 - Martijn Pieters
2
@ninjagecko:你的代码行 >>> intersection = ... 不会在终端上输出结果。你缺少一个明确的 >>> intersection。此外,在你编辑 Counter([{..}]) 输出之前,你的示例是不正确的。最后但并非最不重要的是,在我输入答案并在提示符上测试它时,你的答案仍然相当不正确。我可以向你保证,如果我们的答案看起来相似,那完全是巧合。 - Martijn Pieters
显示剩余4条评论

9

使用collections.Counter来创建每个单词的集合:

>>> from collections import Counter
>>> str_a, str_b = 'aabbcc', 'aabd'
>>> Counter(str_a) & Counter(str_b)
Counter({'a': 2, 'b': 1})
>>> ''.join((Counter(str_a) & Counter(str_b)).elements())
'aab'
计数器(Counter)是一个dict字典的子类,但它会统计初始化序列中所有元素的数量。因此,"aabbcc"会变成Counter({'a': 2, 'b': 2, 'c': 2})计数器(Counter)就像多重集合(multisets),当你在上面使用2来进行交集运算时,它们的数量会被设置为在任一计数器中找到的最小值,忽略任何数量降至0的元素。如果您要计算它们的并集,则将使用最大计数而不是最小计数。

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