将某个关键词后的字符串切片成lis

2024-09-28 22:24:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我是python新手,遇到了一个问题。我要做的是,我有一个字符串,其中包含两个人之间的对话:

str = "  dylankid: *random words* senpai: *random words* dylankid: *random words* senpai: *random words*"

我想用dylankid和senpai作为名称从字符串中创建2个列表:

^{pr2}$

这是我正在挣扎的地方,在列表dylankid中,我想把所有在'dylankid'后面,但在下一个'dylankid'或'senpai'之前的单词放在字符串中 senpai列表也是如此 看起来像这样

dylankid = ["random words", "random words", "random words"]
senpai = ["random words", "random words", "random words"]    

dylankid包含来自dylankid的所有消息,反之亦然。在

我已经研究过将其切片并使用split()re.compile(),但我无法找到一种方法来指定开始切片和停止位置。在

希望它足够清楚,任何帮助将不胜感激:)


Tags: 字符串名称消息列表地方切片random对话
3条回答

这可以收紧,但应该很容易扩展到更多的用户名。在

from collections import defaultdict

# Input string
all_messages = "  dylankid: *random words* senpai: *random words* dylankid: *random words* senpai: *random words*"

# Expected users
users = ['dylankid', 'senpai']

starts = {'{}:'.format(x) for x in users}
D = defaultdict(list)
results = defaultdict(list)

# Read through the words in the input string, collecting the ones that follow a user name
current_user = None
for word in all_messages.split(' '):
    if word in starts:
        current_user = word[:-1]
        D[current_user].append([])
    elif current_user:
        D[current_user][-1].append(word)

# Join the collected words into messages
for user, all_parts in D.items():
    for part in all_parts:
        results[user].append(' '.join(part))

结果是:

^{pr2}$

以下代码将创建一个dict,其中keys是person,value是消息列表:

from collections import defaultdict
import re

PATTERN = '''
    \s*                         # Any amount of space
    (dylankid|senpai)           # Capture person
    :\s                         # Colon and single space
    (.*?)                       # Capture everything, non-greedy
    (?=\sdylankid:|\ssenpai:|$) # Until we find following person or end of string
'''
s = "  dylankid: *random words* senpai: *random words* dylankid: *random words* senpai: *random words*"
res = defaultdict(list)
for person, message in re.findall(PATTERN, s, re.VERBOSE):
    res[person].append(message)

print res['dylankid']
print res['senpai']

它将产生以下输出:

^{pr2}$

您可以使用groupby,拆分单词并使用__contains__进行分组

s = "dylankid: *random words d* senpai: *random words s* dylankid: *random words d*  senpai: *random words s*"
from itertools import groupby

d = {"dylankid:": [], "senpai:":[]}

grps = groupby(s.split(" "), d.__contains__)

for k, v in grps:
    if k:
        d[next(v)].append(" ".join(next(grps)[1]))
print(d)

输出:

^{pr2}$

下一次我们用一个单词的名字来连接。在

如果名称后碰巧没有单词,则可以使用空列表作为下一次调用的默认值:

s = "dylankid: *random words d* senpai: *random words s* dylankid: *random words d*  senpai: *random words s* senpai:"
from itertools import groupby

d = {"dylankid:": [], "senpai:":[]}
grps = groupby(s.split(" "), d.__contains__)

for k, v in grps:
    if k:
        d[next(v)].append(" ".join(next(grps,[[], []])[1]))
print(d)

一些较大字符串的计时:

In [15]: dy, sn = "dylankid:", " senpai:"

In [16]: t = " foo " * 1000

In [17]: s = "".join([dy + t + sn + t for _ in range(1000)])

In [18]: %%timeit
   ....: d = {"dylankid:": [], "senpai:": []}
   ....: grps = groupby(s.split(" "), d.__contains__)
   ....: for k, v in grps:
   ....:     if k:
   ....:         d[next(v)].append(" ".join(next(grps, [[], []])[1]))
   ....: 
1 loop, best of 3: 376 ms per loop

In [19]: %%timeit
   ....: PATTERN = '''
   ....:     \s*                         # Any amount of space
   ....:     (dylankid|senpai)           # Capture person
   ....:     :\s                         # Colon and single space
   ....:     (.*?)                       # Capture everything, non-greedy
   ....:     (?=\sdylankid:|\ssenpai:|$) # Until we find following person or end of string
   ....: '''
   ....: res = defaultdict(list)
   ....: for person, message in re.findall(PATTERN, s, re.VERBOSE):
   ....:     res[person].append(message)
   ....: 
1 loop, best of 3: 753 ms per loop

两者都重新生成相同的输出:

In [20]: d = {"dylankid:": [], "senpai:": []}

In [21]: grps = groupby(s.split(" "), d.__contains__)

In [22]: for k, v in grps:
           if k:                                        
                d[next(v)].append(" ".join(next(grps, [[], []])[1]))
   ....:         

In [23]: PATTERN = '''
   ....:     \s*                         # Any amount of space
   ....:     (dylankid|senpai)           # Capture person
   ....:     :\s                         # Colon and single space
   ....:     (.*?)                       # Capture everything, non-greedy
   ....:     (?=\sdylankid:|\ssenpai:|$) # Until we find following person or end of string
   ....: '''

In [24]: res = defaultdict(list)

In [25]: for person, message in re.findall(PATTERN, s, re.VERBOSE):
   ....:         res[person].append(message)
   ....:     

In [26]: d["dylankid:"] == res["dylankid"]
Out[26]: True

In [27]: d["senpai:"] == res["senpai"]
Out[27]: True

相关问题 更多 >