2015-12-22 27 views
7

の特定のセットに基づいた文字列は、私はどこかの別のリストにリストを解析することができるようにしたい['for', 'or', 'and']のようなキーワードリストを考えると、このような、分割言葉

['happy_feet', 'happy_hats_for_cats', 'sad_fox_or_mad_banana','sad_pandas_and_happy_cats_for_people'] 

のような文字列のリストを持っていますキーワードリストが文字列内で発生し、その文字列を複数の部分に分割します。

例えば、上記のセットは、現在、私は、アンダースコアで各内部文字列を分割し、その後で文字列を再結合、キーワードのインデックスを探してループのために持ってきた

['happy_feet', 'happy_hats', 'cats', 'sad_fox', 'mad_banana', 'sad_pandas', 'happy_cats', 'people'] 

に分割されるだろうアンダースコア。これを行うより速い方法がありますか?

+1

。あなたのアプリケーションには遅すぎますか? – TigerhawkT3

+0

本当に、私はPythonの初心者です。これを行うためのより良い、より簡潔な方法があるかどうかはわかりませんでした。 – SharpObject

+1

一般的には、最適化する前に測定することをお勧めします。 :)基本的な文字列操作は、とにかく、より複雑なアプローチよりも高速です。 – TigerhawkT3

答えて

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

あなたに提供されるサンプルデータセットあなたはいけない_区切り文字と実際に

のための所望の出力が得られます本当にあなただけ

>>> pat = re.compile("_(?:%s)_"%"|".join(split_list)) 
>>> list(itertools.chain(pat.split(line) for line in data)) 
を行うことができますので、長さによって、それをソートする必要があります

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

パターンを動的キーワードのリストから作成されます。

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

1つのリストにそれらを結合するには、使用することができます

result = [] 
for s in l: 
    result.extend(re.split(r"_(?:f?or|and)_", s)) 
+0

これは、単語のセットを処理するための追加のステップが必要です。単語が文字列の先頭または末尾にある場合、これは機能しません。 – Holt

+0

OPで指定された要件ではありませんでした(したがって私の同様の答えに関する免責事項)... +1からこの答えに+1 –

+0

@Holt:そうです、よろしくお願いします。第2の問題が問題かどうかはわかりません。 –

6

あなたは正規表現を使用することができます。文字列'happy_hats_for_cats''_for_'に分割されます。

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

各分割結果:

>>> re.split(r'_for_', 'happy_hats_for_cats') 
['happy_hats', 'cats'] 

が、我々は実際にあなたがいずれかのキーワードで分割して取得(|メタ文字を使用して)選択肢の集合を生成するので、文字列のリストを表示します(分割するものがない場合は1つだけです)。 itertools.chain.from_iterable()を使用すると、それらのリストをすべて1つのlong 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'] 
+0

偉大な心とそのすべて:P –

+1

@JoranBeasley:これは奇妙なモバイルネットワークの瞬間です:-(私の電車の旅の最初の20分(それは来ると行く)の接続性はあまりありません。 –

2

これを実行する別の方法、唯一の組み込みメソッドを使用するには、たとえば_1_のために言って、置換文字列を持つすべての文字列に['for', 'or', 'and']に何のすべての発生を置き換えることです(それができました次いでにおいて、この置換文字列に分割するために、各反復の終了)は、任意の文字列である:

l = ['happy_feet', 'happy_hats_for_cats', 'sad_fox_or_mad_banana','sad_pandas_and_happy_cats_for_people'] 
replacement_s = '_1_' 
lookup = ['for', 'or', 'and'] 
lookup = [x.join('_'*2) for x in lookup] #Changing to: ['_for_', '_or_', '_and_'] 
results = [] 
for i,item in enumerate(l): 
    for s in lookup: 
     if s in item: 
      l[i] = l[i].replace(s,'_1_') 
    results.extend(l[i].split('_1_')) 

OUTPUT:

0おそらく、実際には非常に高速です
['happy_feet', 'happy_hats', 'cats', 'sad_fox', 'mad_banana', 'sad_pandas', 'happy_cats', 'people']