2017-03-29 9 views
0

まず、タイトルがあまり明確でない場合は、申し訳ありませんが、それを正しく定式化するのは難しいです。それは、もし質問があれば、すでに質問されているかどうかはわかりません。文字列のリストの*の代わりに未知の部分文字列を検索してください

したがって、私は文字列のリストを持っていて、すべての可能な部分文字列でターゲットの部分文字列にすべての*を置き換える "手続き的"検索を実行したいと思います。それは大丈夫ですので、ちょうど1 *私はちょうど*で、各文字列を分割し、startswith()および/またはendswith()を使用している。この場合

strList = ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

searchFor('mesh_*') 
# should return: ['mesh_1_TMP', 'mesh_2_TMP'] 


は、ここでの例です。 しかし、検索文字列に*が複数ある場合、同じことを行う方法はわかりません。

私の質問*の代わりに不明な部分文字列を文字列のリストで検索するにはどうすればよいですか?例えば

strList = ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

searchFor('*_1_*') 
# should return: ['obj_1_mesh', 'mesh_1_TMP'] 

ホープすべてが十分に明確です。ありがとう。

+4

正規表現の場合は、 're'を調べるとよいでしょう。 – LoicM

+2

最初の例の期待出力として '['mesh_ok1'、 'mesh_ok2']'に到着する方法を説明してください。 – timgeb

+0

ああ、申し訳ありません。結果を変更せずにサンプルコードを変更したからです。私はそれを今編集する。 – UKDP

答えて

1

私はあなたの場合、正規表現パッケージを使用します。正しい検索クエリを作成するために正規表現を少しは学ばなければならないが、それほど悪くはない。 '。+'はこの場合 '*'とかなり似ています。

import re 

def search_strings(str_list, search_query): 
    regex = re.compile(search_query) 
    result = [] 
    for string in str_list: 
     match = regex.match(string) 
     if match is not None: 
      result+=[match.group()] 
    return result 

strList= ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

print search_strings(strList, '.+_1_.+') 

['obj_1_mesh'、 'mesh_1_TMP']が返されます。私は '* _1_ *'の場合を再現しようとしました。 'mesh_ *'の場合、search_query 'mesh _。+'を作成することができます。 Pythonの正規表現APIへのリンクは次のとおりです。https://docs.python.org/2/library/re.html

+0

ここで非貪欲なマッチングを使うのはいい考えです。 –

+1

それはOPまでです。この特定のケースで直感的にわかりやすいと思ったので、私は欲張りを使用しました。あなたが貪欲でない使用を希望するならば、OPは '+'の代わりに '*'を使います。 – Outis

+0

ありがとう!すべての答えは良いですが、これはあまり凝縮されていないので、私はそれを理解するのが簡単です(私は多くの正規表現を使わず、今は完全に理解していないので)。私はまた、「+」を「*」に変更しました。これはもっと正確です。 – UKDP

3

Unixのようなファイルパターンマッチングを提供する 'fnmatch'の使用を検討してください。詳細はこちらhttp://docs.python.org/2/library/fnmatch.html

from fnmatch import fnmatch 
strList = ['obj_1_mesh', 
     'obj_2_mesh', 
     'obj_TMP', 
     'mesh_1_TMP', 
     'mesh_2_TMP', 
     'meshTMP'] 

searchFor = '*_1_*' 

resultSubList = [ strList[i] for i,x in enumerate(strList) if fnmatch(x,searchFor) ] 

文字列はあなたが常に文字列あなただけのfind関数を使用することができるようになりますを探しているなら、このトリックに

+2

fnmatchのドキュメントへのリンクを提供し、fnmatchが何をしているかを簡単に説明した場合、この回答は少し良いでしょう。単に "fnmatchがunixファイル名ワイルドカードに似たパターンにマッチする能力を提供する"のようなものを言っているだけで、これを良い答えから素晴らしい答えに変える必要があります。 –

0

を行う必要があり、あなたのような何かを得るでしょう:

for s in strList: 
    if s.find(searchFor) != -1: 
     do_something() 

検索する文字列が複数ある場合(abc * 123 * testなど)、各文字列を検索する必要があります。同じ文字列の2番目の文字列を最初に見つけた+それはlenなどです。

1

これを行う最も簡単な方法は、ma3ounの答えに示すようにfnmatchを使用することです。しかし、ここではRegular Expressions、別名正規表現を使用してそれを行う方法があります。

最初にsearchForパターンを変換し、'*'の代わりに'.+?'を「ワイルドカード」として使用します。そして、結果を正規表現のパターンオブジェクトにコンパイルして、複数のテストを効率的に使用できるようにします。

正規表現の構文については、ドキュメントを参照してください。しかし、簡潔に言えば、ドットは(この行の)任意の文字を意味し、+はそれらの1つ以上を探すことを意味し、?は貪欲でないマッチングを意味します。最も長いものではなくパターンに適合する最小の文字列にマッチします(これは貪欲なマッチングがします)。

import re 

strList = ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

searchFor = '*_1_*' 
pat = re.compile(searchFor.replace('*', '.+?')) 

result = [s for s in strList if pat.match(s)] 
print(result) 

出力

['obj_1_mesh', 'mesh_1_TMP'] 

我々はsearchFor = 'mesh_*'を使用している場合、結果は

['mesh_1_TMP', 'mesh_2_TMP'] 

であるこのソリューションは堅牢ませんのでご注意ください。 searchForに正規表現で特別な意味を持つ他の文字が含まれている場合は、escapedである必要があります。実際には、そのsearchFor.replace変換を行うのではなく、まず最初にregex構文を使用してパターンを書き込む方がクリーンです。

関連する問題