如何将文件转换为字典?

105

我有一个由两列组成的文件,即

1 a 
2 b 
3 c

我希望将这个文件读入一个字典中,使得第一列为键,第二列为值,也就是说:

d = {1:'a', 2:'b', 3:'c'}

这个文件很小,所以效率不是问题。

11个回答

180
d = {}
with open("file.txt") as f:
    for line in f:
       (key, val) = line.split()
       d[int(key)] = val

1
你能解释一下 with 语句吗? - VGE
17
这里使用 with 来处理文件清理。当你离开代码块时(无论是正常执行流还是出现异常),文件都会自动关闭。你可以在这里阅读更多关于 Python 上下文管理器的内容:http://effbot.org/zone/python-with-statement.htm - Vlad H
1
for line in open("file.txt"): 做完清理工作。如果f是一个本地值,那么当范围丢失时f会被释放。这个语句有用的唯一情况是长函数(不利于质量),或者您使用全局变量。 - VGE
1
@VGE,for line in open('file.txt')的清理方式并不相同。不是所有的Python实现都一样。 with保证当退出块时文件将被关闭。当for行完成时,可能会调用close。在CPython中,确实会调用,但像IronPython这样的版本具有懒惰的垃圾收集器。 - Mark Tolonen
2
这里真的需要使用int吗?也许他想要将数字转换为字符串? - GL2014
显示剩余5条评论

18

这将把键留作字符串:

with open('infile.txt') as f:
  d = dict(x.rstrip().split(None, 1) for x in f)

4
我认为一个简单的dict([line.split() for line in f])就足够了。 - user225312
@sukhbir:如果你仔细阅读问题,你会发现这不是op想要的。 - SilentGhost
@SilentGhost:我看到原帖想要整数键,但Ignacio的解决方案(以及我删除的那个)将键作为字符串(正如Ignacio自己指出的那样)。 - user225312
我曾经困惑为什么在传递字典参数时不需要使用[]。例如,dict([x.rstrip().split(None, 1) for x in f])而不是dict(x.rstrip().split(None, 1) for x in f)。对于那些有同样疑问的人,前者是生成器表达式而不是列表推导式,这在这里得到了解释:https://www.python.org/dev/peps/pep-0289(PEP-289)。学到了新东西! - peaxol
1
@peaxol:我们使用生成器表达式而不是列表推导式,以避免创建中间列表。 - Ignacio Vazquez-Abrams

11

你也可以使用字典推导式,例如:

with open("infile.txt") as f:
    d = {int(k): v for line in f for (k, v) in [line.strip().split(None, 1)]}

是的,你完全可以在这里使用推导式。但我发现自己越来越少这样做,因为它违反了 Python 之禅的一些规则(“显式优于隐式”和“可读性很重要”)。 - Peter Kassenaar

5
def get_pair(line):
    key, sep, value = line.strip().partition(" ")
    return int(key), value

with open("file.txt") as fd:    
    d = dict(get_pair(line) for line in fd)

1
为什么不使用partitionwith语句? - SilentGhost
@SilentGhost:我不知道分区!但为什么在这种情况下最好使用str.split?关于“with”:也许你可以为我澄清一下:超出范围的文件描述符关闭不就足够了吗?我猜在异常情况下文件可能仍然保持打开状态,我会改变它。 - tokland
partition 更快,专门为此目的创建。 - SilentGhost
无论描述符是否关闭都是实现的细节。with是确保它关闭的简单方法。 - SilentGhost
我认为仍然需要使用 strip - SilentGhost

3

通过字典解析

d = { line.split()[0] : line.split()[1] for line in open("file.txt") }

使用pandas

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]

仅使用pandas仅取第一列。 - Maulik Madhavi
1
以上的解决方案(字典推导式)仅适用于键和值都只有一个单词的情况。如果我的文本文件包含以下数据,我该如何将年份作为键,获胜团队作为值。1903波士顿美国人队 1904没有世界大赛 1905纽约巨人队 1906芝加哥白袜队 1907芝加哥小熊队 1908芝加哥小熊队 - Ridhi
1
@Ridhi 抱歉回复晚了。你可以只在第一个空格处分割字符串 https://dev59.com/dF0a5IYBdhLWcg3wLV8G 或者使用正则表达式作为split()的参数。 - Samer Ayoub
@SamerAyoub- 谢谢。 - Ridhi

2

简单选项

大多数存储字典的方法使用JSON、Pickle或逐行读取。只要您不在Python之外编辑字典,这种简单方法就足以处理复杂的字典。虽然对于较大的字典,Pickle会更好。

x = {1:'a', 2:'b', 3:'c'}
f = 'file.txt'
print(x, file=open(f,'w'))    # file.txt >>> {1:'a', 2:'b', 3:'c'}
y = eval(open(f,'r').read())
print(x==y)                   # >>> True

0

依我之见,更pythonic的做法是使用生成器(可能需要2.7+版本):

with open('infile.txt') as fd:
    pairs = (line.split(None) for line in fd)
    res   = {int(pair[0]):pair[1] for pair in pairs if len(pair) == 2 and pair[0].isdigit()}

这也将过滤掉不以整数开头或不包含恰好两个项目的行


0
如果你喜欢一行代码,可以尝试:
d=eval('{'+re.sub('\'[\s]*?\'','\':\'',re.sub(r'([^'+input('SEP: ')+',]+)','\''+r'\1'+'\'',open(input('FILE: ')).read().rstrip('\n').replace('\n',',')))+'}')

输入FILE = 文件路径,SEP = 键值分隔符字符

虽然不是最优雅或最有效的方法,但仍然非常有趣 :)


0

我有一个需求,需要从文本文件中获取值并将其用作键值对。我的文本文件中的内容是key = value,因此我使用了分割方法,并将分隔符设置为“=”,然后编写了以下代码:

d = {}
file = open("filename.txt")
for x in file:
    f = x.split("=")
    d.update({f[0].strip(): f[1].strip()})

通过使用strip方法,可以删除“=”分隔符之前或之后的任何空格,并以字典格式获得预期数据。

你好,欢迎来到 Stack Overflow!你的方法与其他用户不同,但是你能否编辑一下,将 = 替换为 来回答这个问题呢? - Prunus Persica

-1
import re

my_file = open('file.txt','r')
d = {}
for i in my_file:
  g = re.search(r'(\d+)\s+(.*)', i) # glob line containing an int and a string
  d[int(g.group(1))] = g.group(2)

我认为这不是最佳方法。 - Donovan
@Seafoid说:“文件很小,所以效率不是问题。” 如果文件格式不合理,split() 函数几乎不会悄无声息地工作。 - VGE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接