根据一组单词拆分字符串

Sha*_*ect 7 python regex string

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

['happy_feet', 'happy_hats_for_cats', 'sad_fox_or_mad_banana','sad_pandas_and_happy_cats_for_people'] 
Run Code Online (Sandbox Code Playgroud)

给定一个关键字列表,['for', 'or', 'and']我希望能够将列表解析为另一个列表,如果关键字列表出现在字符串中,则将该字符串拆分为多个部分.

例如,上面的集合将被拆分为

['happy_feet', 'happy_hats',  'cats', 'sad_fox', 'mad_banana', 'sad_pandas', 'happy_cats', 'people']
Run Code Online (Sandbox Code Playgroud)

目前我已经通过下划线拆分每个内部字符串,并且有一个for循环查找关键字的索引,然后通过下划线重新组合字符串.有更快的方法吗?

Tim*_*ker 6

>>> [re.split(r"_(?:f?or|and)_", s) for s in l]
[['happy_feet'],
 ['happy_hats', 'cats'],
 ['sad_fox', 'mad_banana'],
 ['sad_pandas', 'happy_cats', 'people']]
Run Code Online (Sandbox Code Playgroud)

要将它们组合到一个列表中,您可以使用

result = []
for s in l:
    result.extend(re.split(r"_(?:f?or|and)_", s))
Run Code Online (Sandbox Code Playgroud)


Jor*_*ley 6

>>> pat = re.compile("_(?:%s)_"%"|".join(sorted(split_list,key=len)))
>>> list(itertools.chain(pat.split(line) for line in data))
Run Code Online (Sandbox Code Playgroud)

将为您提供的示例数据集提供所需的输出

实际上,使用_分隔符,你真的不需要按长度排序,所以你可以这么做

>>> pat = re.compile("_(?:%s)_"%"|".join(split_list))
>>> list(itertools.chain(pat.split(line) for line in data))
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 6

您可以使用正则表达式:

from itertools import chain
import re

pattern = re.compile(r'_(?:{})_'.format('|'.join([re.escape(w) for w in keywords])))

result = list(chain.from_iterable(pattern.split(w) for w in input_list))
Run Code Online (Sandbox Code Playgroud)

该模式是从您的关键字列表中动态创建的.该字符串'happy_hats_for_cats'分为'_for_':

>>> re.split(r'_for_', 'happy_hats_for_cats')
['happy_hats', 'cats']
Run Code Online (Sandbox Code Playgroud)

但是因为我们实际上生成了一组备选方案(使用|元字符),您可以拆分任何关键字:

>>> re.split(r'_(?:for|or|and)_', 'sad_pandas_and_happy_cats_for_people')
['sad_pandas', 'happy_cats', 'people']
Run Code Online (Sandbox Code Playgroud)

每个拆分结果都会为您提供一个字符串列表(如果没有任何内容可以拆分,则只有一个); 使用itertools.chain.from_iterable()让我们将所有这些列表视为一个长迭代.

演示:

>>> from itertools import chain
>>> import re
>>> keywords = ['for', 'or', 'and']
>>> input_list = ['happy_feet', 'happy_hats_for_cats', 'sad_fox_or_mad_banana','sad_pandas_and_happy_cats_for_people']
>>> pattern = re.compile(r'_(?:{})_'.format('|'.join([re.escape(w) for w in keywords])))    
>>> list(chain.from_iterable(pattern.split(w) for w in input_list))
['happy_feet', 'happy_hats', 'cats', 'sad_fox', 'mad_banana', 'sad_pandas', 'happy_cats', 'people']
Run Code Online (Sandbox Code Playgroud)