Python - 如何将列元素添加到带有计数器的列表中

Python - How to add column elements to a list with a counter

在一个包含两列的文本文件中,我有一些如下所示的行:

N     20
CA    20
C     20
O     20
CB    20
CG    20
CD    20
CE    20
NZ    20
N     21
CA    21
C     21
O     21
CB    21
SG    21

我这样创建了一个嵌套字典:

r_list = ['20', '21']
dictionary = {}
r_dict = {}
a_dict = {}
for r in range(0,len(r_list)):
    r = r_list[r]
    dictionary['C'] = r_dict
    r_dict[r] = a_dict

print dictionary

"""output:

{'C': {'20': {}, '21': {}}}

equal to:

dictionary = {'C': {
                    '20': {},
                    '21': {}
                }
            }
"""

现在,如何根据相对第二列的读数拆分文本文件的第一列?我想将第一列的元素添加到新列表中,直到计数器在第二列中找到“20”;之后,当计数器找到“21”时,它开始在新列表中添加与“21”相关的第一列的元素,依此类推......这样,我就可以使用这些新的元素子列表,例如对于 "r_list",与其他嵌套字典一起,获得如下最终结构:

sublist_1 = ['N', 'CA', 'C', 'O', 'CB', 'CG', 'CD', 'CE', 'NZ']
sublist_2 = ['N', 'CA', 'C', 'O', 'CB', 'SG']

dictionary =    {'C' : {
                    '20': {
                        'N': {},
                        'CA': {},
                        'C': {},
                        'O': {},
                        'CB': {},
                        'CG': {},
                        'CD': {},
                        'CE': {},
                        'NZ': {}
                    },
                    '21': {
                        'N': {},
                        'CA': {},
                        'C': {},
                        'O': {},
                        'CB': {},
                        'SG': {}
                    }
                }
            }

怎么做?

非常感谢,

里卡多

编辑:

我成功地将所有解决方案应用于原始 cif 文件,但是对于 "label_atom_id" 列(第三列),在某些 cif 文件和某些原子中,有引号,如下面的第八列保留在字典中的行和第三列(从零开始:"O5'"):

ATOM   588  O  O4    . DT  B 2 10 ? 33.096 42.342 26.554 1.00 4.81  ? ? ? ? ? ? 29  DT  E O4    1 
ATOM   589  C  C5    . DT  B 2 10 ? 32.273 42.719 24.308 1.00 8.22  ? ? ? ? ? ? 29  DT  E C5    1 
ATOM   590  C  C7    . DT  B 2 10 ? 33.654 42.972 23.700 1.00 10.91 ? ? ? ? ? ? 29  DT  E C7    1 
ATOM   591  C  C6    . DT  B 2 10 ? 31.207 42.767 23.502 1.00 2.00  ? ? ? ? ? ? 29  DT  E C6    1 
ATOM   592  P  P     . DG  B 2 11 ? 25.446 44.301 21.417 1.00 28.24 ? ? ? ? ? ? 30  DG  E P     1 
ATOM   593  O  OP1   . DG  B 2 11 ? 24.109 43.692 21.128 1.00 19.20 ? ? ? ? ? ? 30  DG  E OP1   1 
ATOM   594  O  OP2   . DG  B 2 11 ? 26.212 45.060 20.381 1.00 24.94 ? ? ? ? ? ? 30  DG  E OP2   1 
ATOM   595  O  "O5'" . DG  B 2 11 ? 25.303 45.130 22.804 1.00 27.92 ? ? ? ? ? ? 30  DG  E "O5'" 1 
ATOM   596  C  "C5'" . DG  B 2 11 ? 24.694 44.453 23.923 1.00 19.87 ? ? ? ? ? ? 30  DG  E "C5'" 1 
ATOM   597  C  "C4'" . DG  B 2 11 ? 25.160 44.958 25.273 1.00 19.56 ? ? ? ? ? ? 30  DG  E "C4'" 1 
ATOM   598  O  "O4'" . DG  B 2 11 ? 26.506 44.513 25.519 1.00 22.77 ? ? ? ? ? ? 30  DG  E "O4'" 1 
ATOM   599  C  "C3'" . DG  B 2 11 ? 25.135 46.521 25.375 1.00 19.23 ? ? ? ? ? ? 30  DG  E "C3'" 1 
ATOM   600  O  "O3'" . DG  B 2 11 ? 24.620 46.792 26.672 1.00 20.19 ? ? ? ? ? ? 30  DG  E "O3'" 1 
ATOM   601  C  "C2'" . DG  B 2 11 ? 26.605 46.795 25.327 1.00 18.78 ? ? ? ? ? ? 30  DG  E "C2'" 1 
ATOM   602  C  "C1'" . DG  B 2 11 ? 27.116 45.634 26.159 1.00 21.24 ? ? ? ? ? ? 30  DG  E "C1'" 1 
ATOM   603  N  N9    . DG  B 2 11 ? 28.583 45.580 26.153 1.00 21.14 ? ? ? ? ? ? 30  DG  E N9    1

我试图从文件中删除它们,只有 (O5),但没有成功:

with open(filename,"r") as f:
    lines = f.readlines()

for line in lines:
    column = line.split(None)
    atom = column[3]
    #print atom
    no_double_quotes = atom.replace('"', "").strip()
    #print no_double_quotes
    atom_cleaned = no_double_quotes.replace("'", "").strip()
    atom = atom_cleaned
    print atom

# and write everything back
with open(filename, 'w') as f:
    f.writelines(lines)

控制台输出是正确的,但是没有任何内容写入为字典解析的文件中......有没有更有效和更有效的方法?

编辑 2(最终):

我明白了:双引号(在控制台中写为'"O5 \'"时)嵌入了用于糖(在这种情况下为脱氧核糖)原子编号的撇号字符(\') ) 在核苷酸中,所以我不能删除它们,具有功能意义。明白了这一点,我解决了然后用它的 ASCII 字符 (chr(39)) 替换撇号字符,这样:

for x in atom_record_rows_list:
    atom = x[3]
    #print atom
    no_double_quotes = atom.replace('"', "").strip()
    #print no_double_quotes
    atom_cleaned = no_double_quotes.replace("'", chr(39)).strip()
    x[3] = atom_cleaned
    print x[3]

dict = {"C": {y:{x[3]:{} for x in atom_record_rows_list if x[8] == y} for y in rlist}}
print dict
  1. 通过read方法读取文件。
  2. 创建结果字典。
  3. \n 拆分文件内容,即 split('\n')
  4. 通过 for 循环迭代步骤 2 中的每个元素。
  5. 通过split(" ")
  6. 从每个元素中获取两列值
  7. 在结果字典中添加计数器键。在 except 块中。
  8. 在计数器字典中添加元素名称字典。

代码:

with open("/home/infogrid/Desktop/Work/stack/input.txt", "r") as fp:
    data = fp.read()

result = {'C':{}}
for i in data.strip().split('\n'):
    val_count = [j for j in i.split(' ') if j]
    try:
        result['C'][val_count[1]][val_count[0]] = {}
    except KeyError:
        result['C'][val_count[1]] = {}
        result['C'][val_count[1]][val_count[0]] = {}

import pprint
pprint.pprint(result)

输出:

{'C': {'20': {'C': {},
              'CA': {},
              'CB': {},
              'CD': {},
              'CE': {},
              'CG': {},
              'N': {},
              'NZ': {},
              'O': {}},
       '21': {'C': {}, 'CA': {}, 'CB': {}, 'N': {}, 'O': {}, 'SG': {}}}}

使用 defaultdict 模块从代码中删除 try-except 块。 more info

>>> from collections import defaultdict
>>> result = {'C':defaultdict(dict)}
>>> result['C']['20']['CB'] = {}
>>> result['C']['20']
{'CB': {}}
>>> result['C']['21']
{}
>>> 

听起来你让这件事变得比需要的更难了。 您可以遍历文件中的行,将它们拆分并添加到字典中吗:

dictionary = { 'C': { r : {} for r in ['20', '21'] }}
with open('<filename>', 'r') as file:
    for line in file:
        words = line.split()
        dictionary['C'][words[1]][words[0]] = {}

如果您确实需要子列表,您可以提取子列表:

sublist_1 = dictionary['C']['20'].keys()
sublist_2 = dictionary['C']['21'].keys()

但是你必须记住,字典是没有顺序的,所以它们会以不同的顺序出现。

您可以使用听写理解为您完成此操作

inp = """N     20
CA    20
C     20
O     20
CB    20
CG    20
CD    20
CE    20
NZ    20
N     21
CA    21
C     21
O     21
CB    21
SG    21"""

mappings = [i.split() for i in inp.split("\n")]
rlist = set(x[1] for x in mappings)
dicts = {"C": {y:{x[0]:{} for x in mappings if  x[1] == y} for y in rlist}}

>>> print dicts
{'C': 
 {'20': {'C': {},
   'CA': {},
   'CB': {},
   'CD': {},
   'CE': {},
   'CG': {},
   'N': {},
   'NZ': {},
   'O': {}},
  '21': {'C': {}, 
   'CA': {}, 
   'CB': {}, 
   'N': {}, 
   'O': {}, 
   'SG': {}}
 }
}