Python poniendo líneas no uniformes en un diccionario

El archivo de entrada tiene este aspecto:

A 3.00 B 4.00 C 5.00 D 6.00
E 3.20 F 6.00 G 8.22
H 9.00 
I 9.23 J 89.2
K 32.344

Y quiero que los caracteres sean las claves en un diccionario mientras que los flotadores son los valores.

Aquí está la falla que no funciona que tengo hasta ahora.

def main():
   #Input File
   reader = open('candidate.txt', 'r'

   my_dictionary = {}
   i=0
   for line in reader.readlines():
      variable = line.split(' ')[i]
      value = line.split(' ')[i+1]
      my_dictionary[variable]= value
      i+=2

      print my_dictionary

if __name__ == '__main__':
  main()

preguntado el 03 de julio de 12 a las 07:07

Piense en su código por un momento. i se incrementa en 2 por cada línea, ¿verdad? Entonces obtienes el primer par de la línea 1, el segundo de la línea 2, y así sucesivamente, lo que claramente no es lo que quieres, ¿verdad? Necesita dos bucles for anidados, uno para líneas y otro para obtener todos los pares dentro de una línea (si desea seguir usando bucles for, hay opciones más eficientes, consulte la respuesta de guettli, por ejemplo). -

Básicamente, debe iterar sobre los elementos de su lista en pares (clave, valor). Aquí hay una respuesta extensa que muestra diferentes técnicas: stackoverflow.com/questions/4628290/pairs-from-single-list - Me gusta el pairwise función de la respuesta aceptada. -

@ usuario1497892 por favor acepte una respuesta. O agregue comentarios sobre por qué las respuestas no resuelven su problema. -

3 Respuestas

s='''A 3.00 B 4.00 C 5.00 D 6.00
E 3.20 F 6.00 G 8.22
H 9.00 
I 9.23 J 89.2
K 32.344
'''

s=s.split()
d=dict(zip(s[::2], s[1::2]))
print d

En contexto:

my_dict = dict()
for line in reader.readlines():
    pairs = line.split()
    for key, value in zip(pairs[::2],pairs[1::2]):
        my_dict[key] = value # strip() not needed

Respondido 03 Jul 12, 08:07

¡Oye! Gracias por la respuesta, pero ¿hay alguna manera de hacer esto sin modificar el archivo de entrada agregando comillas? El archivo de entrada se me está dando. - user1497892

Muy bien, aunque no usaría este código exacto si fuera el OP. Siempre es mejor evitar leer todo el archivo de una vez cuando sea posible. Sin embargo, este código es una demostración muy concisa de una buena idea. - lev levitsky

@user1497892, es un literal de cadena multilínea. No necesita comillas en el archivo de entrada. Además, para que el código funcione, necesita saber exactamente qué readlines, readline y read retorno en un objeto de archivo. Consulte los documentos. - lev levitsky

Aquí hay una solución que usa iteradores que opera en una secuencia (y, por lo tanto, no depende de leer primero la entrada completa):

from itertools import izip

def group(iterable, n):
    """Yield iterable's items n at a time"""
    args = [iter(iterable)]*n
    return izip(*args)


def dictize(stream):
    r = {}
    for line in stream:
        for k,v in group(line.split(), 2):
            r[k] = v
    return r


from StringIO import StringIO

testinput = """A 3.00 B 4.00 C 5.00 D 6.00
E 3.20 F 6.00 G 8.22
H 9.00 
I 9.23 J 89.2
K 32.344"""

teststream = StringIO(testinput)

print dictize(teststream)

Si puede usar comprensiones de diccionario, puede reemplazar el dictize función con una sola línea:

print {k:v for line in teststream for k,v in group(line.split(),2)}

Respondido 03 Jul 12, 08:07

with open('candidate.txt', 'r') as reader:
    print dict(zip(*[iter(reader.read().split())]*2))

With el flujo de archivo abierto llamado reader we read como un todo y luego split en pedazos por espacio en blanco. Ahora tenemos una lista de palabras que transformamos en un iterator y ponerlo en una lista y multiplicarlo veces 2 para hacer una lista de dos iteradores iguales. Estos son zipped en pares como entrada para un dictionario.

Respondido 03 Jul 12, 14:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.