您的代码是合理的,但这里有一个替代方案:
import collections
with open('grid_file.txt', 'r') as f:
columns = next(f).split()
matrix = collections.defaultdict(dict)
for line in f:
items = line.split()
row, vals = items[0], items[1:]
for col, val in zip(columns, vals):
matrix[col][row] = int(val)
print(matrix)
产生
defaultdict(<type 'dict'>, {'A': {'A': 0, 'C': 6, 'B': 3}, 'C': {'A': 2, 'C': 0, 'B': 5}, 'B': {'A': 1, 'C': 7, 'B': 0}})
一些技巧:
采用
with open(...) as f
...
代替
f = open(...)
f.close()
因为当Python离开
with-block
. 通过使用with
,您将永远不会忘记关闭文件句柄,即使发生异常,文件句柄在离开with-block
.
f.readlines()
一般来说,如果可以的话,最好避免。这会将整个文件放入列表中。这对内存来说可能很繁重,尤其是在文件很大的情况下。通常
with open(...) as f:
for line in f:
可以代替使用。
如果您创建matrix
一个collections.default(dict)那么
默认情况下matrix[field]
将是一个dict
。所以你可以跳过初始化:
for key in keys:
matrix[key] = {}
Adefaultdict
是 的子类dict
,因此您可以像使用 a 一样使用它dict
。如果您不喜欢它的打印方式,或者想停止matrix
自动将空 dict 分配给
matrix[key]
for any key
,您可以将 defaultdict 转换回常规dict
:
matrix = dict(matrix)
for-loops
如果可以,请避免使用数字索引。
for i, c in enumerate(chars[1:]):
尽管这对于大多数类 C 语言来说都是必需的,但 Python 有一个更好的方法:循环遍历项目本身:
for col, val in zip(columns, vals):
这使代码更具可读性,因为它为您真正感兴趣的对象分配了一个变量名,而不仅仅是一个索引,然后您必须将其组合成诸如keys[i-1]
. 它还可以帮助您避免当您必须将索引调整一时可能发生的“非一”错误,如keys[i-1]
.
另一种可能性是不使用嵌套字典,而是使用 2 元组(列、行)作为键:
with open('grid_file.txt', 'r') as f:
columns = next(f).split()
matrix = {}
for line in f:
items = line.split()
row, vals = items[0], items[1:]
for col, val in zip(columns, vals):
matrix[col, row] = int(val)
print(matrix)
产量
{('B', 'C'): 7, ('A', 'A'): 0, ('B', 'B'): 0, ('B', 'A'): 1, ('C', 'A'): 2, ('C', 'B'): 5, ('C', 'C'): 0, ('A', 'B'): 3, ('A', 'C'): 6}
然后您可以像这样访问矩阵中的(列,行):
print(matrix['A','C'])
# 6
顺便说一句,如果你安装pandas:
import pandas as pd
import io
text = '''\
A B C
A 0 1 2
B 3 0 5
C 6 7 0'''
df = pd.read_table(io.BytesIO(text), sep='\s+')
print(df.to_dict())
产量
{'A': {'A': 0, 'B': 3, 'C': 6},
'B': {'A': 1, 'B': 0, 'C': 7},
'C': {'A': 2, 'B': 5, 'C': 0}}