¿Cómo convertir un archivo en un diccionario?

94

Tengo un archivo que consta de dos columnas, es decir,

1 a 
2 b 
3 c

Deseo leer este archivo en un diccionario de modo que la columna 1 sea la clave y la columna 2 sea el valor, es decir,

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

El archivo es pequeño, por lo que la eficiencia no es un problema.

Darren J. Fitzpatrick
fuente

Respuestas:

154
d = {}
with open("file.txt") as f:
    for line in f:
       (key, val) = line.split()
       d[int(key)] = val
Vlad H
fuente
1
¿Podría explicar la declaración con?
VGE
12
withse usa aquí para manejar la limpieza del archivo. Cuando abandone el bloque (ya sea por el flujo de ejecución normal o por una excepción), el archivo se cerrará automáticamente. Puede leer más sobre los administradores de contexto en Python aquí: effbot.org/zone/python-with-statement.htm
Vlad H
1
for line in open("file.txt"):haga la limpieza de la misma manera. Y si f es un valor local, fse libera cuando se pierde el alcance. El único caso en el que esta declaración es útil es para una función larga (no es buena para la calidad) o si usa una variable global.
VGE
1
@VGE, for line in open('file.txt')no no hacer la limpieza de la misma manera. No todas las implementaciones de Python son iguales. withgarantiza que el archivo se cerrará cuando se salga del bloque. Cuando la forlínea esté completa, close se puede llamar. CPythonlo hará, pero versiones como IronPythontienen recolectores de basura perezosos.
Mark Tolonen
2
¿Es realmente necesario int aquí? ¿Quizás quería que los números fueran cadenas?
GL2014
15

Esto dejará la clave como una cadena:

with open('infile.txt') as f:
  d = dict(x.rstrip().split(None, 1) for x in f)
Ignacio Vázquez-Abrams
fuente
2
Un simple dict([line.split() for line in f])es suficiente, en mi opinión.
user225312
@sukhbir: si lees la pregunta, verás que eso no es lo que op quiere.
SilentGhost
@SilentGhost: Leí que el OP quiere claves como enteros, pero la solución de Ignacio (así como la que eliminé), tiene claves como una cadena (como señaló el propio Ignacio).
user225312
Estaba confundido por qué no necesitamos [] al pasar el argumento dict. es decir, en dict([x.rstrip().split(None, 1) for x in f])lugar de dict(x.rstrip().split(None, 1) for x in f). Para aquellos que piensan lo mismo, la primera es una expresión generadora en lugar de una lista de comprensión como se explica aquí: python.org/dev/peps/pep-0289(PEP-289) . ¡Aprendí algo nuevo!
peaxol
1
@peaxol: Usamos una expresión generadora en lugar de una lista de comprensión para no crear una lista intermedia.
Ignacio Vazquez-Abrams
7

Si su versión de Python es 2.7+, también puede usar una comprensión de dictado como:

with open('infile.txt') as f:
  {int(k): v for line in f for (k, v) in (line.strip().split(None, 1),)}
wim
fuente
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)
tokland
fuente
1
¿por qué no partition? y withdeclaración?
SilentGhost
@SilentGhost: ¡No sabía nada de la partición! pero ¿por qué es mejor str.split en este caso? con respecto a "con": tal vez pueda aclararme esto: ¿no es suficiente salir del alcance para que se cierre el descriptor de archivo? Supongo que, en una excepción, el archivo principal permanece abierto, lo cambiaré.
tokland
partitiones más rápido y está creado exactamente para este propósito.
SilentGhost
si el descriptor está cerrado o no es un detalle de la implementación. withes una forma sencilla de asegurarse de que lo sea.
SilentGhost
todavía requeriría strip, diría yo.
SilentGhost
3

Por comprensión de diccionario

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

O por pandas

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]
Samer Ayoub
fuente
Por pandas solo toma la primera columna
Maulik Madhavi
1
@Samer Ayoub La solución anterior (comprensión del diccionario) funciona si tanto las claves como el valor tienen una palabra. Si mi archivo de texto tiene los siguientes datos, ¿cómo hago el año como claves y el equipo ganador como valores? 1903 Boston Americans 1904 No World Series 1905 New York Giants 1906 Chicago White Sox 1907 Chicago Cubs 1908 Chicago Cubs
Ridhi
1
@Ridhi Lo siento por la respuesta tardía. Puede dividir solo en el primer espacio stackoverflow.com/questions/30636248/… O usar una expresión regular como argumento para split ()
Samer Ayoub
@ SamerAyoub- Gracias.
Ridhi
1

En mi humilde opinión, un poco más pitónico para usar generadores (probablemente necesite 2.7+ para esto):

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()}

Esto también filtrará las líneas que no comiencen con un número entero o que no contengan exactamente dos elementos

Holger Bille
fuente
0
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)
VGE
fuente
9
re? ¿seriamente?
SilentGhost
No creo que este sea el mejor enfoque.
Donovan
@Seafoid dijo "El archivo es pequeño, por lo que la eficiencia no es un problema". split()no funciona casi en silencio si el formato de archivo no es sensato.
VGE
0

Si te encantan los one liners, prueba:

d=eval('{'+re.sub('\'[\s]*?\'','\':\'',re.sub(r'([^'+input('SEP: ')+',]+)','\''+r'\1'+'\'',open(input('FILE: ')).read().rstrip('\n').replace('\n',',')))+'}')

Archivo de entrada = ruta al archivo, SEP = carácter separador de valor-clave

No es la forma más elegante o eficiente de hacerlo, pero no obstante es bastante interesante :)

srami
fuente
0

Aquí hay otra opción ...

events = {}
for line in csv.reader(open(os.path.join(path, 'events.txt'), "rb")):
    if line[0][0] == "#":
        continue
    events[line[0]] = line[1] if len(line) == 2 else line[1:]
Robel Robel Lingstuyl
fuente
0

Opción simple

La mayoría de los métodos para almacenar un diccionario utilizan JSON, Pickle o lectura de líneas. Siempre que no esté editando el diccionario fuera de Python, este método simple debería ser suficiente incluso para diccionarios complejos. Aunque Pickle será mejor para diccionarios más grandes.

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
A. Oeste
fuente