5

基本的に、フォルダ内のすべてのファイルのリストがあります。簡略化されたバージョンでは次のようになります。

file_list = [ 'drug.resp1.17A.tag', 'drug.resp1.96A.tag', 'drug.resp1.56B.tag', 'drug.resp2.17A.tag', 'drug.resp2.56B.tag', 'drug.resp2.96A.tag']

別のリスト:

drug_list = [ '17A', '96A', '56B']

これら 2 つのリストを次のように辞書に結合したいと考えています。

dictionary = {
    '17A' : ['drug.resp1.17A.tag' , 'drug.resp2.17A.tag' ], 
    '96A' : ['drug.resp1.96A.tag' , 'drug.resp2.96A.tag' ], 
    '56B' : ['drug.resp1.56B.tag' , 'drug.resp2.56B.tag' ]}

私はこのようにしようと思ったが行き詰まった!

dict_drugs = {}
for file in file_list:
    list_filename = file.split('.')
    for elem in drug_list:
        if elem in list_filename:

この後、要素を辞書に結合するにはどうすればよいですか、またはこれを完全に間違っていますか?

4

11 に答える 11

5

内側のループは必要ありません

>>> file_list = [ 'drug.resp1.17A.tag', 'drug.resp1.96A.tag', 'drug.resp1.56B.tag', 'drug.resp2.17A.tag', 'drug.resp2.56B.tag', 'drug.resp2.96A.tag']
>>> dictonary = {}
... for i in file_list:
...     k = i.split('.')[-2]
...     if k in dictonary:
...         dictonary[k].append(i)
...     else:
...         dictonary[k] = [i]
>>> dictonary
62: {'17A': ['drug.resp1.17A.tag', 'drug.resp2.17A.tag'],
 '56B': ['drug.resp1.56B.tag', 'drug.resp2.56B.tag'],
 '96A': ['drug.resp1.96A.tag', 'drug.resp2.96A.tag']}
>>> 

Drug_list に存在する値のみが必要かどうかをもう一度確認します

file_list に次が含まれている場合を意味します。

file_list = [「drug.resp1.18A.tag」、「drug.resp1.96A.tag」、「drug.resp1.56B.tag」、「drug.resp2.17A.tag」、「drug.resp2.56B.タグ」、「drug.resp2.96A.tag」]

>>> drug_list = [ '17A', '96A', '56B']
... dictonary = {}
... for i in file_list:
...     k = i.split('.')[-2]
...     if k in drug_list:
...         if k in dictonary:
...             dictonary[k].append(i)
...         else:
...             dictonary[k] = [i]
>>> 

大文字を効率的に行うもう 1 つの方法:

dictonary = dict(((i,[]) for i in drug_list))

dictonary = {drug: [] for drug in drug_list}  # As @J.F. Sebastian suggested.

for file in file_list:
    k = file.split('.')[-2]
    if k in dictonary:
        dictonary[k].append(file)
于 2012-12-27T16:01:32.800 に答える
3

itertoolsandを使用してみることができますgroupby(詳細については、こちらを参照してください)。その目的は、key「グループ化」するために使用する値を提供することです (適切にグループ化するには、アイテムを並べ替える必要があるため、ピースが必要であることにfile_list注意してください)。 sorted:

In [1]: from itertools import groupby

In [2]: file_list = [ 'drug.resp1.17A.tag', 'drug.resp1.96A.tag', 'drug.resp1.56B.tag', 'drug.resp2.17A.tag', 'drug.resp2.56B.tag', 'drug.resp2.96A.tag']

In [3]: drug_list = [ '17A', '96A', '56B']

In [4]: grouper = lambda x: x.split('.')[-2]

In [5]: d = {}

In [6]: for key, group in groupby(sorted(file_list, key=grouper), key=grouper):
   ...:     d[key] = list(group)
   ...:     
   ...:     

In [7]: d
Out[7]: 
{'17A': ['drug.resp1.17A.tag', 'drug.resp2.17A.tag'],
 '56B': ['drug.resp1.56B.tag', 'drug.resp2.56B.tag'],
 '96A': ['drug.resp1.96A.tag', 'drug.resp2.96A.tag']}

これが行うことは、分割後に最後から 2 番目の要素で各アイテムをfile_listグループ化し、結果のグループをその場所で見つかったキーに割り当てることです。部分は、少しスペースを節約することです。grouperリストを特別なキーで並べ替えてから、関数を使用して同じキーでグループ化するlambdaため、その関数を別の変数に保存して、groupby句が少し読みやすくなるようにします。 .

drug_list注意すべきことの 1 つは、これはあなたにとって重要である場合とそうでない場合があるあなたの に依存しないということです。たとえば、これは次のようなものdrug.resp1.1000A.tag1000Agroup にグループ化します。

@JFSebastian で述べられているようにdrug_list、リストを に変換することで、自分で見つかった薬のみを効率的に含めることができますset。これには、一意のアイテムのみが含まれ、O(1) ルックアップを持つという利点があります (つまり、if a in b検索する必要がないことを意味します)。リストの場合と同様に、オブジェクト全体):

In [10]: drug_list = set(drug_list)

In [11]: only_listed = (f for f in file_list if grouper(f) in drug_list)

In [12]: only_listed
Out[12]: <generator object <genexpr> at 0x24fcbe0>

In [13]: for key, group in groupby(sorted(only_listed, key=grouper), key=grouper):
   ....:     d[key] = list(group)
   ....:     
   ....:     

In [14]: d
Out[14]: 
{'17A': ['drug.resp1.17A.tag', 'drug.resp2.17A.tag'],
 '56B': ['drug.resp1.56B.tag', 'drug.resp2.56B.tag'],
 '96A': ['drug.resp1.96A.tag', 'drug.resp2.96A.tag']}
于 2012-12-27T16:04:20.160 に答える
3

すべてのファイルが薬物リストに対応する一致を持っていると仮定します。

dic = {d:[] for d in drug_list}
for file in file_list: dic[file.split('.')[-2]].append(file)
于 2012-12-27T16:00:44.740 に答える
1

問題をできるだけ単純に保つようにしてください。

file_list = [ 'drug.resp1.17A.tag', 'drug.resp1.96A.tag', 'drug.resp1.56B.tag',      'drug.resp2.17A.tag', 'drug.resp2.56B.tag', 'drug.resp2.96A.tag']
drug_list = [ '17A', '96A', '56B']
result = {}

for drug in drug_list:
   result[drug] = []
   for file_name in file_list:
       if drug in file_name:
           result[drug].append(file_name)
于 2012-12-27T16:19:27.857 に答える
1

itertools.ifilterこれを単一行の辞書内包にすることができます。

>>> from itertools import ifilter
>>> file_list = [ 'drug.resp1.17A.tag', 'drug.resp1.96A.tag', 'drug.resp1.56B.tag', 'drug.resp2.17A.tag', 'drug.resp2.56B.tag', 'drug.resp2.96A.tag']
>>> drug_list = [ '17A', '96A', '56B']
>>> { k: list( ifilter( lambda v: k in v, file_list ) ) for k in drug_list }
{
    '56B': ['drug.resp1.56B.tag', 'drug.resp2.56B.tag'], 
    '96A': ['drug.resp1.96A.tag', 'drug.resp2.96A.tag'], 
    '17A': ['drug.resp1.17A.tag', 'drug.resp2.17A.tag']
}
于 2012-12-27T16:05:09.257 に答える
1

これを試して:

dict_drugs = {s:[] for s in drug_list}

for file in file_list:
    list_filename = file.split('.')
    for elem in list_filename:
        if elem in drug_list:
            dict_drugs[elem].append(file)

チェックの順序を変更したので、ファイル名の薬ではなく、辞書のファイル名の一部を検索します。

また、辞書は最初にすべての薬物の空のリストで初期化されたことに注意してください。

于 2012-12-27T15:59:44.003 に答える
1

2 つの内包表記を使用して、データ構造を自然にループできます。

dict((drug, [file for file in file_list if drug in file]) for drug in drug_list)

これを分解しましょう。辞書を作成する必要があるので、そのためにリスト内包表記を使用しましょう。

dict((a, str(a + " is the value")) for a in [1, 2, 3])

最も外側の部分は、dict を作成するリスト内包表記です。(キー、値) の形式の 2 つのタプルを作成することで、辞書を取得するために dict() を呼び出すことができます。私たちの答えでは、ドラッグをキーとして設定し、値を別のリスト内包表記から構築されたリストに設定します。これまでのところ、次のことがわかっています。

{'17A': [SOMETHING],
 '56B': [SOMETHING],
 '96A': [SOMETHING]}

次に、何かを埋める必要があります。これが、内部理解が行うことです。あなたのロジックは、薬物のテキストがファイルに表示されるかどうかを確認することのようです。私たちはすでに薬を持っているので、次のように言うことができます:

[file for file in file_list if drug in file]

これは、ファイル リストを実行し、その中に薬物が表示された場合に追加します。

Python 2.7 以降では、dict() を使用する代わりに辞書内包表記を使用できます。その場合、次のようになります。

{drug: [file for file in file_list if drug in file] for drug in drug_list}

これは、2 タプルを作成して変換するボイラー プレートをすべてなくすことができるため、はるかに明確です。

内包表記は、コードを記述する優れた方法です。これは、何をしようとしているのかを非常に明確に説明する傾向があるためです。ただし、これは辞書を作成する最も効率的な方法ではないことに注意してください。これは、すべての薬物のすべてのファイルを処理するためです。ファイルのリストが非常に長い場合、これは非常に遅くなる可能性があります。

編集:私の最初の答えはナンセンスでした。懺悔として、こんな細かいものを作りました。

于 2012-12-27T16:00:00.510 に答える
1

薬物リストの文字列が常にファイル リストの文字列の部分文字列である場合、3 つの単純なコード行でそれを行うことができます。

In [1]: d = {}

In [2]: for drug in drug_list:
  ....:     d[drug] = [file for file in file_list if drug in file]

In [3]: d
Out[3]: 
{'17A': ['drug.resp1.17A.tag', 'drug.resp2.17A.tag'],
 '56B': ['drug.resp1.56B.tag', 'drug.resp2.56B.tag'],
 '96A': ['drug.resp1.96A.tag', 'drug.resp2.96A.tag']} 
于 2012-12-27T16:07:34.277 に答える
0

欠点は、薬の数がわからないことであり、将来的には新薬が登場する可能性があります。

私はFarukの答え、ほとんど私の考え方が好きですが、drug_listの作成を追加します。

drug_list = list(set([x.split('.')[-2] for x in file_list]))
于 2012-12-27T17:00:11.623 に答える
0

これはうまくいくようです

import re

file_list = [ 'drug.resp1.17A.tag', 'drug.resp1.96A.tag', 'drug.resp1.56B.tag', 'drug.resp2.17A.tag', 'drug.resp2.56B.tag', 'drug.resp2.96A.tag']
drug_list = [ '17A', '96A', '56B']
drugIdRegex = re.compile(r"drug\.resp\d+\.(?P<drugId>\d+\w+)\.tag")

if __name__ == "__main__":
    results = dict.fromkeys(drug_list, None)
    for file_name in file_list:
        matcher = drugIdRegex.match(file_name)
        if matcher and matcher.group("drugId") in results:
            if results[matcher.group("drugId")] is None:
                results[matcher.group("drugId")] = list()
            results[matcher.group("drugId")].append(file_name)
    print "Results: %s" % results

ただし、リスト内包表記を 1 行で記述できると確信しています。それはクールだろう(しかし、私は方法がわからない):)

于 2012-12-27T16:04:15.197 に答える
0
    python 3.2


   {i:[v for v in file_list if i in v] for i in drug_list}
于 2012-12-27T16:31:47.480 に答える