2012-09-04 16 views
5

Tengo un diccionario como este creado con Python.Impresión bonita salida en un formato de árbol lateral en la ventana de la consola

d = {'a': ['Adam', 'Book', 4], 'b': ['Bill', 'TV', 6, 'Jill', 'Sports', 1, 'Bill', 'Computer', 5], 'c': ['Bill', 'Sports', 3], 'd': ['Quin', 'Computer', 3, 'Adam', 'Computer', 3], 'e': ['Quin', 'TV', 2, 'Quin', 'Book', 5], 'f': ['Adam', 'Computer', 7]} 

Quería imprimir esto en un formato de árbol lateral en lugar de en la consola. Intenté imprimir bastante, pero cuando el diccionario se alarga, se vuelve difícil de leer.

Por ejemplo, con este diccionario, devolvería:

a -> Book -> Adam -> 4 
b -> TV -> Bill -> 6 
    -> Sports -> Jill -> 1 
    -> Computer -> Bill -> 5 
c -> Sports -> Bill -> 3 
d -> Computer -> Quin -> 3 
       -> Adam -> 3 
e -> TV -> Quin -> 2 
    Book -> Quin -> 5 
f -> Computer -> Adam -> 7 

Esencialmente, la impresión bonita está organizado por la actividad, o el artículo en segunda posición en la lista, a continuación, por su nombre y luego por la número.

El ejemplo de salida anterior es solo un ejemplo. Intenté trabajar con Pretty print a tree, pero no pude encontrar la manera de convertirlo en un formato lateral.

Respuesta

1
def treePrint(tree): 
    for key in tree: 
     print key, # comma prevents a newline character 
     treeElem = tree[key] # multiple lookups is expensive, even amortized O(1)! 
     for subElem in treeElem: 
      print " -> ", subElem, 
      if type(subElem) != str: # OP wants indenting after digits 
       print "\n " # newline and a space to match indenting 
     print "" # forces a newline 
+0

se ve bien ... cualquier manera para que sea similar a la del árbol de impresión bonita uno donde tiene un formato de árbol? – user1530318

+0

Si está buscando algún tipo de solución de profundidad de árbol recursiva, podría tener un caso base donde los datos no son iterables, de lo contrario recurse. No conozco muy bien el módulo de pprint, así que no sé realmente qué es lo que espera que pueda hacer. – rsegal

+0

El uso del nombre de una palabra clave como 'dict' para un argumento o nombre de variable se considera de mala calidad, al igual que el tipo de comprobación. – martineau

3

Así es como yo lo haría. Como el árbol solo tiene dos niveles de profundidad, a pesar de lo que parezca implicar el formato de salida deseado, no es necesario utilizar la recursividad para recorrer su contenido, ya que la iteración funciona bastante bien. Probablemente esto no se parece en nada al código #f al que hizo referencia, ya que no conozco el idioma, pero es mucho más corto y más legible, al menos para mí.

from itertools import izip 

def print_tree(tree): 
    for key in sorted(tree.iterkeys()): 
     data = tree[key] 
     previous = data[0], data[1], data[2] 
     first = True 
     for name, activity, value in izip(*[iter(data)]*3): # groups of three 
      activity = activity if first or activity != previous[1] else ' '*len(activity) 
      print '{} ->'.format(key) if first else ' ', 
      print '{} -> {} -> {}'.format(activity, name, value) 
      previous = name, activity, value 
      first = False 

d = {'a': ['Adam', 'Book', 4], 
    'b': ['Bill', 'TV', 6, 'Jill', 'Sports', 1, 'Bill', 'Computer', 5], 
    'c': ['Bill', 'Sports', 3], 
    'd': ['Quin', 'Computer', 3, 'Adam', 'Computer', 3], 
    'e': ['Quin', 'TV', 2, 'Quin', 'Book', 5], 
    'f': ['Adam', 'Computer', 7]} 

print_tree(d) 

Salida:

a -> Book -> Adam -> 4 
b -> TV -> Bill -> 6 
    Sports -> Jill -> 1 
    Computer -> Bill -> 5 
c -> Sports -> Bill -> 3 
d -> Computer -> Quin -> 3 
       -> Adam -> 3 
e -> TV -> Quin -> 2 
    Book -> Quin -> 5 
f -> Computer -> Adam -> 7 

actualización

Para organizar la salida por su nombre en lugar de la actividad que había necesidad de cambiar tres líneas como se indica a continuación:

from itertools import izip 

def print_tree(tree): 
    for key in sorted(tree.iterkeys()): 
     data = tree[key] 
     previous = data[0], data[1], data[2] 
     first = True 
     for name, activity, value in sorted(izip(*[iter(data)]*3)): # changed 
      name = name if first or name != previous[0] else ' '*len(name) # changed 
      print '{} ->'.format(key) if first else ' ', 
      print '{} -> {} -> {}'.format(name, activity, value) # changed 
      previous = name, activity, value 
      first = False 

Salida después de la modificación:

a -> Adam -> Book -> 4 
b -> Bill -> Computer -> 5 
      -> TV -> 6 
    Jill -> Sports -> 1 
c -> Bill -> Sports -> 3 
d -> Adam -> Computer -> 3 
    Quin -> Computer -> 3 
e -> Quin -> Book -> 5 
      -> TV -> 2 
f -> Adam -> Computer -> 7 
+0

línea 3 debe ser datos = árbol [clave], no d [tecla], ¿verdad? – user1530318

+0

Además, ¿cómo lo haría si lo quisiera organizado por el nombre y no por la actividad, así organizado por el primer elemento en la lista, no el segundo. a -> adam -> libro -> 4 por ejemplo – user1530318

+0

Sí, la línea 3 estaba mal (una sobrante de antes de convertirla en una función). Lo arreglé y también actualicé mi respuesta para mostrarme caliente y modificarla para organizar la salida por nombre y no por actividad. – martineau

8

Puede echar un vistazo al código del ETE toolkit. La función _asciiArt produce buenas representaciones de árboles incluso with internal node labels

from ete2 import Tree 
t = Tree("(((A,B), C), D);") 
print t 

#    /-A 
#   /---| 
#  /---|  \-B 
# | | 
#----|  \-C 
# | 
#  \-D 
Cuestiones relacionadas