2016-04-10 22 views
4

Python'da yeniyim ve bir sorunla karşılaşıyorum. Ya ben iki kişi arasındaki bir konuşmayı içeren bir dize var bunu yapmaya çalışıyorum: Ben adları gibi dylankid ve Senpai kullanarak dizesinden 2 listeleri oluşturmak isteyenBelirli anahtar sözcükler listeden sonra bir Dize Dilimleme

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

:

dylankid = [ ] 
senpai = [ ] 

ve Burada ben mücadele ediyorum, ben dylankid içinde ben dize içinde 'dylankid' sonra gelen tüm kelimeleri yerleştirmek istiyorum ama bir sonraki 'dylankid' veya 'senpai' aynıdır senpai liste için gidiyor bu yüzden bir şey gibi görünüyor bu

Dylankid'den gelen tüm mesajları içeren, ve tam tersi,

.

split() ve re.compile()'u kullanarak dilimlemeyi inceledim, ancak dilimlemeyi başlatmak ve nerede duracağını belirlemek için bir yol olduğunu anlayamıyorum.

Umarım yeterince açık, herhangi bir yardım mutluluk duyacağız edildi :) tuşları kişilerdir ve değerler mesajların listesi nerede

+0

Bunu [.partition] bulabilirsiniz (https://docs.python.org/2/library/stdtypes.html#str.part: aynı çıktıyı retuurn ition) işlevi, belirttiğiniz ayırıcıdan sonra dizeleri ayırabileceği için yararlıdır. –

+0

İçlerinde ':' ile rastgele kelimeler var mı? –

+0

@PadraicCunningham evet –

cevap

4

ardından kod dicti oluşturur:

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'] 

Aşağıdaki çıktıyı üretecek :

['*random words*', '*random words*'] 
['*random words*', '*random words*'] 
+0

İki not: 1-Muhtemelen 're.finditer' daha iyi olurdu ... 2-Daha iyisi 'pat' o zaman 'pat.finditer' olarak deseninizi yeniden düzenleyin. –

+1

@Iron Fist: 're.finditer', çok fazla eşleşme olması durumunda hafızayı koruyacak, ancak bu senaryoda' re.compile 'işlevini kullanmanın motivasyonu ne olurdu? Aynı sebepten dolayı – niemmi

+0

're.finditer' performansını kullanıyorum ama OP'nin ilgisi gibi görünmüyor. –

1

Bu sıkılabilir, ancak daha fazla kullanıcı adına genişletmek kolay olmalıdır.

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)) 

sonuçlar şöyle:

defaultdict(
    <class 'list'>, 
    {'senpai': ['*random words*', '*random words*'], 
    'dylankid': ['*random words*', '*random words*']} 
) 
2

Kelimeleri bölme ve __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) 

Çıktı kullanarak gruplama, bir GroupBy kullanabilirsiniz:

{'dylankid:': ['*random words d*', '*random words d*'], 'senpai:': ['*random words s*', '*random words s*']} 

Her zaman biz almak Dict ismimizde bu ismi next(v) ile kullanıyoruz, bir sonraki dizgiye, bir sonraki dizgeye geri dönmek için str.join kullanarak bir sonraki adıma geçiyoruz. Daha büyük dizeleri üzerinde

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) 

Bazı zamanlamaları:

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 

İkisi Bir adından sonra hiçbir kelime var olduysa

, bir sonraki çağrı için varsayılan değer olarak boş listeleri kullanabilirsiniz

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 
İlgili konular