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

时间:2012-12-27 15:49:40

标签: 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 = {
    '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:

在此之后我可以做什么才能将元素加入字典中,或者我完全错误了?

11 个答案:

答案 0 :(得分: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.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)

答案 1 :(得分:3)

假设所有文件在药物清单中都有相应的匹配:

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

答案 2 :(得分:3)

您可以尝试使用itertoolsgroupby(有关详细信息,请参阅here),其目标是提供用于“分组”的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.tag之类的内容分组到1000A组中。

如@JFSebastian所述,您可以通过将列表转换为drug_list来有效地仅包含您set中找到的药物,if a in b仅包含唯一项目并且具有O的好处(1)查找(意思是说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']} 不需要搜索整个对象,如列表的情况):

{{1}}

答案 3 :(得分: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)

我更改了支票的顺序,因此它会搜索字典中的部分文件名而不是文件名中的药物。

另外,请注意,字典在开头时已初始化,每个药物都有一个空列表。

答案 4 :(得分: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])

最外面的部分是创建一个字典的列表理解。通过创建表单(键,值)的2元组,我们可以简单地在其上调用dict()来获取字典。在我们的回答中,我们将药物设置为关键,并将值设置为从另一个列表理解构建的列表。到目前为止,我们有:

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

现在我们需要填写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元组和转换的所有锅炉板都可以完成。

理解是编写代码的一种很好的方式,因为它往往非常清楚地描述了你的意思。值得注意的是,这不是构建字典的最有效方式,因为它贯穿每种药物的每个文件。如果文件列表很长,则可能非常慢。

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

答案 5 :(得分: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']
}

答案 6 :(得分: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']} 

答案 7 :(得分: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)

答案 8 :(得分: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

虽然我很确定你可以用一行中的列表推导来做到这一点!!那很酷(但我不知道怎么样):)

答案 9 :(得分:0)

    python 3.2


   {i:[v for v in file_list if i in v] for i in drug_list}

答案 10 :(得分:0)

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

我真的很喜欢法鲁克的答案,几乎是我的思维方式,但我会把它添加到drug_list创作中。

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