找到某些单词后出现的所有子字符串

时间:2018-06-06 18:12:14

标签: python regex

我使用的字符串如下:

"AAAA xsdfe123 BBBB 1jhfhfs CCCC 13 AAAA hjhj 300 DDDD hfh3 BBBB 14 x"

我需要获得AAAA,BBBB,CCCC和DDDD之后的所有值,请注意AAAA,BBBB,CCCC和DDDD可以按任何顺序排列,并且可以重复多次。 或者有时我们可能会有一些(不是全部),例如“BBBB 14 x”

我正在寻找的输出应采用以下格式:

{"AAAA":["xsdfe123", "hjhj 300"], "BBBB":["1jhfhfs", "14 x"], "CCCC":["13"], "DDDD":["hfh3"]}

我怎么能在python中有效地做到这一点?

4 个答案:

答案 0 :(得分:2)

这是使用collections.defaultdict进行O(n)解决方案的一种方法。由于我们使用str.split,因此有必要跟踪计数,以便我们加入出现在键后面的多个值。

有一个边缘大小写,其中您的字符串不以键开头,未计入。我把它留作练习。

from collections import defaultdict

s = 'AAAA xsdfe123 BBBB 1jhfhfs CCCC 13 AAAA hjhj 300 DDDD hfh3 BBBB 14 x'

d = defaultdict(list)

valid_keys = {'AAAA', 'BBBB', 'CCCC', 'DDDD'}

for item in s.split():
    if item in valid_keys:
        count = 0
        key = item
    else:
        count += 1
        if count == 1:
            d[key].append(item)
        else:
            d[key][-1] = '{0} {1}'.format(d[key][-1], item)

defaultdict(list,
            {'AAAA': ['xsdfe123', 'hjhj 300'],
             'BBBB': ['1jhfhfs', '14 x'],
             'CCCC': ['13'],
             'DDDD': ['hfh3']})

答案 1 :(得分:2)

我认为你可以通过正则表达式匹配(使用前瞻告诉我们在哪里停止)和defaultdict来存储数据:

import collections
import re

text = "AAAA xsdfe123 BBBB 1jhfhfs CCCC 13 AAAA hjhj 300 DDDD hfh3 BBBB 14 x"

pattern = "(AAAA|BBBB|CCCC|DDDD) (.*?)(?:$|(?= AAAA| BBBB| CCCC| DDDD))"

results = collections.defaultdict(list)
for abcd, following_text in re.findall(pattern, text):
    results[abcd].append(following_text)

输出:

>>> results
defaultdict(list,
            {'AAAA': ['xsdfe123', 'hjhj 300'],
             'BBBB': ['1jhfhfs', '14 x'],
             'CCCC': ['13'],
             'DDDD': ['hfh3']})

答案 2 :(得分:0)

您可以使用itertools.groupby

import itertools
import re
s = "AAAA xsdfe123 BBBBjhfhfs CCCC 13 AAAA hjhj 300 DDDD hfh3 BBBB 14 x"
headers = ['AAAA', 'BBBB', 'CCCC', 'DDDD']
new_s = re.findall('{}|\w+'.format('|'.join(headers)), s)
new_s = [list(b) for a, b in itertools.groupby(new_s, key=lambda x:x in headers)]
grouped_s = [new_s[i]+new_s[i+1] for i in range(0, len(new_s), 2)]
final_result = {a:[' '.join(i[1:]) for i in b] for a, b in itertools.groupby(sorted(grouped_s, key=lambda x:x[0]), key=lambda x:x[0])}

输出:

{'AAAA': ['xsdfe123', 'hjhj 300'], 'BBBB': ['jhfhfs', '14 x'], 'CCCC': ['13'], 'DDDD': ['hfh3']}

答案 3 :(得分:0)

这是我执行此操作的基本方法:

{'AAAA': ['xsdfe123', 'hjhj 300'], 'BBBB': ['1jhfhfs', '14 x'], 'CCCC': ['13'], 'DDDD': ['hfh3']}

结果:

names

我只是简单地使用任何A-Z作为样本数据中给出的分隔符​​来切断字符串。然后将它们分配为字典的键和值。有很多聪明的方法可以做到这一点,我只是想让它简单易读。