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

我想将这两个列表组合成一个字典,这样:

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

有效地做大写的另一种方法:

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

假设所有文件在药物列表中都有对应的匹配项:

dic = {d:[] for d in drug_list}
for file in file_list: dic[file.split('.')[-2]].append(file)
于 2012-12-27T16:00:44.740 回答
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']}

这样做是在拆分后按倒数第二个元素对您的每个项目进行file_list分组,然后将结果组分配给在该位置找到的键。部分是为了grouper节省一点空间 - 因为我们将通过我们的特殊键对列表进行排序,然后使用该lambda函数按相同的键进行分组,我们只是将该函数存储在一个单独的变量中,以便该groupby子句更易于阅读.

需要注意的一件事是,这不取决于您的drug_list,这可能对您很重要,也可能不重要。例如,这会将类似的东西分组drug.resp1.1000A.tag1000A组中。

正如@JFSebastian 所提到的,您可以drug_list通过将列表转换为 a来有效地仅包含在您的列表中找到的那些药物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 回答
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])

最外面的部分是一个创建字典的列表理解。通过创建 (key, value) 形式的 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

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

如果药物列表中的字符串始终是文件列表中字符串的子字符串,则可以使用三个简单的代码行来完成。

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 回答
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 回答
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

尽管我很确定您可以在一行中使用列表推导来做到这一点!那会很酷(但我不知道如何):)

于 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 回答
0

问题是你不知道药物的数量,未来可能会有新的药物出现。

我真的很喜欢 Faruk 的回答,这几乎是我的思维方式,但我会将其添加到 drug_list 创建中。

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