使用词典理解从文件中读取
我经常需要从(通常是制表符分隔的值)文件读取数据并将它们转换为字符串。通常我只需要将其中一列映射到另一列,但也可能会对值进行一些处理(例如剥离空白)。我一直在努力想出一个词典理解模式来做到这一点,但我一直遇到小的滋扰,使我无法始终如一地以最简洁和可理解的方式实施它。我有一种感觉,可能有更好的方法。使用词典理解从文件中读取
因此,这里有(一些)我曾尝试的方式,并在那里出了错:
with open(path) as f: return {line.split("\t")[0].strip(): line.split("\t")[1].strip() for line in f}
这是我常常最终使用。它允许我修改键和值,并且可以在任何列上工作(例如,如果我想将值从第三列映射到第一列)。明显的问题是line.split()
部分的重复。有没有办法将line.split("\t")
绑定到一个临时变量,或者直接将值解包到变量中?
with open(path) as f: return dict(line.split("\t")[:2] for line in f)
我刚刚想出了这个。它适用于这个简单的案例(只是将第一列映射到第二列,没有任何处理),但不能推广到其他案例。额外的处理很难做到,所用的列必须相邻。这也不是一个严格的词典理解,因为它使用切片而无法变成一个。
d = dict() for line in open(path): d.update({line.split("\t")[0]: line.split("\t")[1]}) return d
当然,我可以先创建字典,然后用每行更新。但是现在我必须创建字典并单独归还,并且代码重复仍然存在。
我也玩过嵌套的词典解释和解压缩分解行为变量,但遇到了不同的问题。
可以排序的做到这一点,通过把周围的东西你f
:
def tabsplit(file_object):
for line in file_object:
yield line.split("\t")
再后来:
with open(path) as f:
return {left.strip(): right.strip() for left, right, *rest in tabsplit(f)}
有趣的是,我没有尝试过以任何方式使用生成器......但是,这是我早些时候暗示的拆包问题开始发挥作用的地方。输入文件可能包含不同数量的选项卡 - 例如,可能存在属于最后一列的尾部值。这些文件然后会抛出一个ValueError,我不知道如何处理字典的理解。这些文件通常还包含不需要在字典中的其他列 - 通过将它们解压缩为_,_,...可能会忽略它们,但我也没有发现它。 –
所以你想忽略除前两个之外的每一列?看到我的编辑丢掉'* rest'。 – L3viathan
太棒了,谢谢! –
不知道为什么创建字典第一个将无法正常工作
result = {}
with open(path) as f:
for line in f:
columns = line.split("\t")
key = columns[0] # first item is the key right?
result[key] = columns[1]
当然,它确实有效,但我试图尽可能简洁地做到这一点。这就是为什么我不喜欢单独的声明和返回步骤 - 即使这将是最可读的解决方案之一。 –
@塞巴斯蒂安:简洁并不总是==更好。可读性和可维护性非常重要,效率通常无关紧要,比如97%的时间。请参阅[_什么时候优化_](https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize)。 – martineau
@martineau我知道,这正是我问这个问题的原因。找到一个我始终可以使用的代码模式可以让我始终如一地使用代码模式,从而提高长期可维护性和可理解性。如果我可以用较少的线条找到一个图案,我可能会更喜欢这一点,因为它的滚动较少 - 我倾向于在IPython笔记本中工作,而其他线条加起来非常快...... –
你正在尝试优化可能I/O约束的东西,所以没有做任何事情,就像创建字典一样快或无线最少量的代码很可能会产生很大的不同。 – martineau