快速选择字符串列表中所有元素的方法,这些元素至少包含另一个列表中的一个子字符串

问题描述 投票:0回答:1

我有一个这样的字符串列表:

samples = ['2345_234_1.0_1.35_001', '0345_123_2.09_1.3_003', ...]

列表可能很长(最坏情况下最多 10^6 个元素)。我有另一个包含一些子字符串的列表:

matches = ['7895_001', '3458_669', '0345_123', ...]

我想创建一个列表

matched_samples
,其中仅包含
samples
的元素,其中包含
matches
的一个或多个元素。例如,
samples[1]
matched_samples
结束,因为
matches[3]
samples[1]
的子串。我可以做这样的事情:

matched_samples = [s for s in samples if any(xs in s for xs in matches)]

然而,这看起来像一个双循环,所以它不会很快。还有其他选择吗?如果

samples
是一个
pandas
数据框,我可以简单地做:

matches_regex = '|'.join(matches)
matched_samples = samples[samples['sample'].str.contains(matches_regex)]

是否有类似的快速替代列表?

python pandas regex list list-comprehension
1个回答
0
投票

你可以做和你的熊猫例子一样的事情。

import re

samples = ['2345_234_1.0_1.35_001', '0345_123_2.09_1.3_003']
matches = ['7895_001', '3458_669', '0345_123']

pattern = re.compile(f"""{"|".join(re.escape(m) for m in matches)}""")
>>> [ s for s in samples if pattern.search(s) ]
['0345_123_2.09_1.3_003']

如果您的示例中没有换行符 - 您也可以将其转换为字符串并在模式周围使用

.findall()
(?:).*

不确定这是否会对速度产生影响。

>>> pattern = re.compile(f"""(?:{"|".join(re.escape(m) for m in matches)}).*""")
>>> pattern
re.compile(r'(?:7895_001|3458_669|0345_123).*', re.UNICODE)
>>> pattern.findall("\n".join(samples))
['0345_123_2.09_1.3_003']
© www.soinside.com 2019 - 2024. All rights reserved.