如何根据列表中设置的顺序,按键中包含的子字符串对Python字典进行排序?



我对Python很陌生,我被一个任务困住了。首先,我制作了一个包含许多序列名称的fasta文件的文件到一个字典中,然后设法只选择我想要的那些,基于包含在列表"flu_genes"中定义的键中的子字符串。

现在我正试图根据列表"flu_genes"中定义的子字符串的顺序重新排序此字典中的项。我完全卡住了;我发现了一种基于列表中的键顺序重新排序的方法,但这不是我的情况,因为顺序不是由键定义的,而是由键内的子字符串定义的。还应该补充说,在这种情况下,子字符串以格式"_GENE"结束,但是它可以在字符串的中间以相同的格式,也许">GENE",因此我宁愿不依赖于代码来查找字符串末尾的子字符串。我希望这是足够清楚,并提前感谢任何帮助!

"full_genome.fasta"
>A/influenza/1/1_NA
atgcg
>A/influenza/1/1_NP
ctgat
>A/influenza/1/1_FluB
agcta
>A/influenza/1/1_HA
tgcat
>A/influenza/1/1_FluC
agagt
>A/influenza/1/1_M
tatag
consensus = {}
flu_genes = ['_HA', '_NP', '_NA', '_M']

with open("full_genome.fasta", 'r') as myseq:                 
for line in myseq:
line = line.rstrip()                                      
if line.startswith('>'):
key = line[1:]                                
else:
if key in consensus:                              
consensus[key] += line
else:
consensus[key] = line                         

flu_fas = {key : val for key, val in consensus.items() if any(ele in key for ele in flu_genes)}
print("Dictionary after removal of keys : " + str(flu_fas))
>>>Dictionary after removal of keys : {'>A/influenza/1/1_NA': 'atgcg', '>A/influenza/1/1_NP': 'ctgat', '>A/influenza/1/1_HA': 'tgcat', '>A/influenza/1/1_M': 'tatag'}
#reordering by keys order (not going to work!) as in: https://try2explore.com/questions/12586065
reordered_dict = {k: flu_fas[k] for k in flu_genes}

字典基本上是无序的,但作为python3的实现细节,它记住了它的插入顺序,并且您以后不会更改任何内容,因此您可以做您正在做的事情。

当然,问题是您没有使用实际的键。让我们建立一个键的列表,并根据你的标准进行排序。然后你可以做其他的事情,除了使用实际的键。

flu_genes = ['_HA', '_NP', '_NA', '_M']
def get_gene_index(k):
for index, gene in enumerate(flu_genes):
if k.endswith(gene):
return index
raise ValueError('I thought you removed those already')

reordered_keys = sorted(flu_fas.keys(), key=get_gene_index)
reordered_dict = {k: flu_fas[k] for k in reordered_keys}
for k, v in reordered_dict.items():
print(k, v)

A/influenza/1/1_HA tgcat
A/influenza/1/1_NP ctgat
A/influenza/1/1_NA atgcg
A/influenza/1/1_M tatag

通常情况下,我不会做n平方排序,但我假设数据文件中的行数远远大于flu_genes的数量,使其本质上是一个固定常数。

对于您的应用程序,这可能是也可能不是最好的数据结构,但我将把它留给代码审查。

这是因为您试图用不存在的字典键重新排序它。你的钥匙是

['>A/influenza/1/1_NA', '>A/influenza/1/1_NP', '>A/influenza/1/1_HA', '>A/influenza/1/1_M']

不匹配列表

['_HA', '_NP', '_NA', '_M']

你首先需要转换它们使它们匹配,因为我们知道它在以下划线开头的字符串末尾的模式,我们可以拆分下划线并获得最后的匹配。

consensus = {}
flu_genes = ['_HA', '_NP', '_NA', '_M']

with open("full_genome.fasta", 'r') as myseq:                 
for line in myseq:
line = line.rstrip()
if line.startswith('>'):
sequence = line
gene = line.split('_')[-1]      
key = f"_{gene}"
else:
consensus[key] = {
'sequence': sequence,
'data': line
}                       

flu_fas = {key : val for key, val in consensus.items() if any(ele in key for ele in flu_genes)}
print("Dictionary after removal of keys : " + str(flu_fas))
reordered_dict = {k: flu_fas[k] for k in flu_genes}

最新更新