Python 如果模式匹配,则将两个列表合并到字典中

Python 如果模式匹配,则将两个列表合并到字典中,python,list,dictionary,Python,List,Dictionary,我基本上有一个文件夹中所有文件的列表,在简化版本中如下所示: 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

我基本上有一个文件夹中所有文件的列表,在简化版本中如下所示:

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:
在这之后,我可以做些什么来将元素加入到字典中,还是我做的完全错误?

试试以下方法:

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)
我更改了检查顺序,因此它在字典中搜索文件名的一部分,而不是在文件名中搜索药物


另外,请注意,字典一开始就初始化为每种药物的空列表。

您可以使用两种理解来自然循环数据结构

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]
这将贯穿文件列表并在药物出现时添加它

在Python2.7及更高版本中,可以使用字典理解而不是dict()。在这种情况下,它看起来像:

{drug: [file for file in file_list if drug in file] for drug in drug_list}
这是非常清楚的,因为所有的锅炉板,使2元组和转换可以做到

理解是编写代码的一种很好的方式,因为理解往往是对您要做的事情的非常清晰的描述。值得注意的是,这并不是构建词典的最有效方法,因为它贯穿了每种药物的每个文件。如果文件列表很长,这可能会很慢


编辑:我的第一个答案是胡说八道。作为忏悔,我做了这个详细的说明。

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

dic = {d:[] for d in drug_list}
for file in file_list: dic[file.split('.')[-2]].append(file)

你不需要内环

>>> 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.resp1.18A.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']
... 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)
这似乎有效

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
重新导入
文件列表=['drug.resp1.17A.tag'、'drug.resp1.96A.tag'、'drug.resp1.56B.tag'、'drug.resp2.17A.tag'、'drug.resp2.56B.tag'、'drug.resp2.96A.tag']
药物清单=['17A'、'96A'、'56B']
drugIdRegex=re.compile(r“druge\.resp\d+\(?P\d+\w+\.tag))
如果名称=“\uuuuu main\uuuuuuuu”:
结果=dict.fromkeys(药物列表,无)
对于文件列表中的文件名:
matcher=drugIdRegex.match(文件名)
如果结果中包含matcher和matcher.group(“药物ID”):
如果结果[matcher.group(“drugId”)]为无:
结果[matcher.group(“drugId”)]=list()
结果[matcher.group(“drugId”)].append(文件名)
打印“结果:%s”%Results

虽然我很确定你可以在一行中列出理解!!这很酷(但我不知道怎么做):

您可以尝试使用
itertools
groupby
(有关更多信息,请参阅),其目标是提供一个
值,用于对
文件列表进行“分组”
(请注意,
已排序的
条目是必需的,因为项目需要按排序顺序正确分组):

这样做的目的是按照拆分后倒数第二个元素对
文件列表中的每个项目进行分组,然后将结果组分配给在该位置找到的键。
分组部分是为了节省一点空间,因为我们将按特殊键对列表进行排序,然后使用
l按同一键进行分组ambda
函数,我们只需将该函数存储在一个单独的变量中,这样
groupby
子句就更容易阅读了

需要注意的一点是,这并不取决于您的
drug\u列表,它可能对您很重要,也可能对您不重要。例如,这会将类似
drug.resp1.1000A.tag的内容分组到
1000A
组中

正如@J.F.Sebastian所提到的,通过将列表转换为
集合
,您可以有效地只包括在
药物列表
中找到的那些药物,这将只包括唯一的项目,并且具有O(1)查找的好处(这意味着如果b中的a不需要像列表那样搜索整个对象,那么说
):

[10]中的
:药品清单=设置(药品清单)
在[11]中:仅列出=(如果石斑鱼(f)在药物列表中,则f代表文件列表中的f)
在[12]中:仅列出
出[12]:
在[13]中:对于键,在groupby中分组(已排序(仅列出),键=grouper,键=grouper):
..:d[键]=列表(组)
....:     
....:     
In[14]:d
出[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']]

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

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

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

尽量使问题尽可能简单:

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)

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

我真的很喜欢法鲁克的答案,这和我的思维方式差不多,但我想把它添加到《毒品清单》中

drug_list = list(set([x.split('.')[-2] for x in file_list]))

如果你投了反对票,请留下评论,bcoz关于这个问题的答案是正确和有效的
我会反击+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)
    python 3.2


   {i:[v for v in file_list if i in v] for i in drug_list}
drug_list = list(set([x.split('.')[-2] for x in file_list]))