Comment convertir un fichier en dictionnaire?

94

J'ai un fichier comprenant deux colonnes, c'est à dire,

1 a 
2 b 
3 c

Je souhaite lire ce fichier dans un dictionnaire tel que la colonne 1 est la clé et la colonne 2 la valeur, c'est-à-dire,

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

Le fichier est petit, donc l'efficacité n'est pas un problème.

Darren J. Fitzpatrick
la source

Réponses:

154
d = {}
with open("file.txt") as f:
    for line in f:
       (key, val) = line.split()
       d[int(key)] = val
Vlad H
la source
1
Pouvez-vous expliquer la déclaration avec?
VGE
12
withest utilisé ici pour gérer le nettoyage des fichiers. Lorsque vous quittez le bloc (soit simplement par le flux d'exécution normal, soit par une exception), le fichier sera automatiquement fermé. Vous pouvez en savoir plus sur les gestionnaires de contexte en Python ici: effbot.org/zone/python-with-statement.htm
Vlad H
1
for line in open("file.txt"):faites le nettoyage de la même manière. Et si f est une valeur locale, le fest libéré lorsque la portée est perdue. Le seul cas où cette instruction est utile est pour une fonction longue (pas bon pour la qualité), ou si vous utilisez une variable globale.
VGE
1
@VGE, for line in open('file.txt')ne fait pas le nettoyage de la même manière. Toutes les implémentations Python ne sont pas identiques. withgarantit que le fichier sera fermé à la sortie du bloc. Lorsque la forligne est complète, close peut être appelée. CPythonce sera le cas, mais les versions comme IronPythonont des garbage collector paresseux.
Mark Tolonen
2
Est-ce vraiment nécessaire ici? Peut-être voulait-il que les nombres soient des chaînes?
GL2014
15

Cela laissera la clé sous forme de chaîne:

with open('infile.txt') as f:
  d = dict(x.rstrip().split(None, 1) for x in f)
Ignacio Vazquez-Abrams
la source
2
Un simple dict([line.split() for line in f])suffit, imo.
user225312
@sukhbir: si vous lisez la question, vous verrez que ce n'est pas ce que veut op.
SilentGhost le
@SilentGhost: J'ai lu que l'OP veut des clés comme des entiers, mais la solution d'Ignacio (ainsi que celle que j'ai supprimée), a des clés comme une chaîne (comme l'a souligné Ignacio lui-même).
user225312
Je ne savais pas pourquoi nous n'avons pas besoin de [] lors du passage de l'argument dict. c'est à dire dict([x.rstrip().split(None, 1) for x in f])au lieu de dict(x.rstrip().split(None, 1) for x in f). Pour ceux qui pensent la même chose, la première est une expression de générateur au lieu de la compréhension de liste comme expliqué ici: python.org/dev/peps/pep-0289(PEP-289) . J'ai appris quelque chose de nouveau!
peaxol
1
@peaxol: Nous utilisons une expression de générateur au lieu d'une compréhension de liste afin de ne pas créer de liste intermédiaire.
Ignacio Vazquez-Abrams
7

Si votre version python est 2.7+, vous pouvez également utiliser une compréhension de dict comme:

with open('infile.txt') as f:
  {int(k): v for line in f for (k, v) in (line.strip().split(None, 1),)}
wim
la source
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
la source
1
pourquoi pas partition? et withdéclaration?
SilentGhost
@SilentGhost: Je ne connaissais pas la partition! mais pourquoi est-il préférable de str.split dans ce cas? concernant "avec": peut-être pouvez-vous clarifier ceci pour moi: n'est-il pas suffisant de sortir du champ pour que le descripteur de fichier soit fermé? Je suppose que dans une exception le fichier principal reste ouvert, je le changerai.
tokland
partitionest plus rapide et est créé exactement dans ce but.
SilentGhost le
que le descripteur soit fermé ou non est un détail de mise en œuvre. withest un moyen simple de s'assurer que c'est le cas.
SilentGhost le
il faudrait encore strip, je dirais.
SilentGhost
3

Par la compréhension du dictionnaire

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

Ou par des pandas

import pandas as pd 
d = pd.read_csv("file.txt", delimiter=" ", header = None).to_dict()[0]
Samer Ayoub
la source
Par pandas ne prend que la première colonne
Maulik Madhavi
1
@Samer Ayoub La solution ci-dessus (compréhension du dictionnaire) fonctionne si les clés et la valeur ne font qu'un seul mot. Si mon fichier texte contient les données suivantes, comment faire de l'année une clé et une équipe gagnante en tant que valeurs. 1903 Américains de Boston 1904 Aucune série mondiale 1905 Giants de New York 1906 White Sox de Chicago 1907 Cubs de Chicago 1908 Cubs de Chicago
Ridhi
1
@Ridhi Désolé pour la réponse tardive. Vous pouvez soit fractionner sur le premier espace uniquement stackoverflow.com/questions/30636248/... Ou utiliser une expression régulière comme argument pour split ()
Samer Ayoub
@ SamerAyoub- Merci.
Ridhi
1

IMHO un peu plus pythonique pour utiliser des générateurs (vous avez probablement besoin de 2.7+ pour cela):

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

Cela filtrera également les lignes ne commençant pas par un entier ou ne contenant pas exactement deux éléments

Holger Bille
la source
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
la source
9
re? sérieusement?
SilentGhost du
Je ne pense pas que ce soit la meilleure approche.
Donovan le
@Seafoid a déclaré: "Le fichier est petit, donc l'efficacité n'est pas un problème." split()ne fonctionne pas presque silencieusement si le format de fichier n'est pas sain.
VGE du
0

Si vous aimez une doublure, essayez:

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

Input FILE = Chemin d'accès au fichier, SEP = Caractère séparateur clé-valeur

Ce n'est pas la manière la plus élégante ou la plus efficace de le faire, mais tout de même assez intéressante :)

srami
la source
0

Voici une autre option ...

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
la source
0

Option simple

La plupart des méthodes de stockage d'un dictionnaire utilisent JSON, Pickle ou la lecture de lignes. À condition que vous n'éditez pas le dictionnaire en dehors de Python, cette méthode simple devrait suffire même pour les dictionnaires complexes. Bien que Pickle soit meilleur pour les grands dictionnaires.

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. Ouest
la source