2016-07-22 10 views
12

Mam słownik list, a listy są dość długie. Jak mogę go wydrukować w taki sposób, aby pokazać tylko kilka elementów z listy? Oczywiście, mogę napisać funkcję niestandardową do tego, ale czy istnieje jakiś wbudowany sposób lub biblioteka, która może to osiągnąć? Na przykład podczas drukowania dużych ramek danych, pandas drukuje to ładnie w krótkim czasie.Python ładny słownik list, skrócone listy

Ten przykład ilustruje lepiej co mam na myśli:

obj = {'key_1': ['EG8XYD9FVN', 
    'S2WARDCVAO', 
    'J00YCU55DP', 
    'R07BUIF2F7', 
    'VGPS1JD0UM', 
    'WL3TWSDP8E', 
    'LD8QY7DMJ3', 
    'J36U3Z9KOQ', 
    'KU2FUGYB2U', 
    'JF3RQ315BY'], 
'key_2': ['162LO154PM', 
    '3ROAV881V2', 
    'I4T79LP18J', 
    'WBD36EM6QL', 
    'DEIODVQU46', 
    'KWSJA5WDKQ', 
    'WX9SVRFO0G', 
    '6UN63WU64G', 
    '3Z89U7XM60', 
    '167CYON6YN']} 

Pożądany wyjście: coś takiego:

{'key_1': 
    ['EG8XYD9FVN', 'S2WARDCVAO', '...'], 
'key_2': 
    ['162LO154PM', '3ROAV881V2', '...'] 
} 
+1

Można też spojrzeć na [ 'repr' Module] (https: // docs. python.org/2/library/repr.html) ('reprlib' w Py3), szczególnie ustawienie' maxlist': rep = Repr(); rep.maxlist = 3; print rep.repr (obj) 'Teraz połączenie tego z' pprint' jest prawdziwym wyzwaniem. –

+0

Awesome! To jest najlepsza odpowiedź i dokładnie to, czego potrzebowałem. Czy możesz dodać jako odpowiedź? @LukasGraf – CentAu

+0

Wygląda na to, że Michael Hoff już pracuje nad odpowiedzią reprlib, więc właśnie przegłosowałem to :) –

Odpowiedz

3

Gdyby nie do drukowania ładna, moduł reprlib byłoby do zrobienia: bezpieczne, eleganckie i konfigurowalny obsługę głęboko zagnieżdżone i rekurencyjne/self-przedstawieniu struktury danych jest to, co zostało wykonane dla.

Jednak okazuje się, że łączenie modułów nie jest trywialne, przynajmniej nie udało mi się wymyślić czystej drogi bez zerwania (niektórych) z ładnych aspektów drukowania.

Zamiast więc, oto rozwiązanie, które po prostu podklas PrettyPrinter przyciąć/skrót list w miarę potrzeby:

from pprint import PrettyPrinter 


obj = { 
    'key_1': [ 
     'EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 
     'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY', 
    ], 
    'key_2': [ 
     '162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 
     'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN', 
    ], 
    # Test case to make sure we didn't break handling of recursive structures 
    'key_3': [ 
     '162LO154PM', '3ROAV881V2', [1, 2, ['a', 'b', 'c'], 3, 4, 5, 6, 7], 
     'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN', 
    ] 
} 


class CroppingPrettyPrinter(PrettyPrinter): 

    def __init__(self, *args, **kwargs): 
     self.maxlist = kwargs.pop('maxlist', 6) 
     return PrettyPrinter.__init__(self, *args, **kwargs) 

    def _format(self, obj, stream, indent, allowance, context, level): 
     if isinstance(obj, list): 
      # If object is a list, crop a copy of it according to self.maxlist 
      # and append an ellipsis 
      if len(obj) > self.maxlist: 
       cropped_obj = obj[:self.maxlist] + ['...'] 
       return PrettyPrinter._format(
        self, cropped_obj, stream, indent, 
        allowance, context, level) 

     # Let the original implementation handle anything else 
     # Note: No use of super() because PrettyPrinter is an old-style class 
     return PrettyPrinter._format(
      self, obj, stream, indent, allowance, context, level) 


p = CroppingPrettyPrinter(maxlist=3) 
p.pprint(obj) 

Wyjście z maxlist=3:

{'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', '...'], 
'key_2': ['162LO154PM', 
      '3ROAV881V2', 
      [1, 2, ['a', 'b', 'c'], '...'], 
      '...']} 

Wyjście z maxlist=5 (wyzwalacze rozdzielenia programów listy w oddzielnych wierszach):

{'key_1': ['EG8XYD9FVN', 
      'S2WARDCVAO', 
      'J00YCU55DP', 
      'R07BUIF2F7', 
      'VGPS1JD0UM', 
      '...'], 
'key_2': ['162LO154PM', 
      '3ROAV881V2', 
      'I4T79LP18J', 
      'WBD36EM6QL', 
      'DEIODVQU46', 
      '...'], 
'key_3': ['162LO154PM', 
      '3ROAV881V2', 
      [1, 2, ['a', 'b', 'c'], 3, 4, '...'], 
      'KWSJA5WDKQ', 
      'WX9SVRFO0G', 
      '...']} 

Uwagi:

  • To stworzy kopie list. W zależności od rozmiaru struktur danych może to być bardzo kosztowne pod względem wykorzystania pamięci.
  • To dotyczy tylko specjalnego przypadku z listami. Równoważne zachowanie musiałoby zostać wprowadzone w przypadku dykt, krotek, zestawów, frozensets, ... aby ta klasa była powszechnego użytku.
+0

Zabawne, miałem podobny prototyp. Ale nie podobały mi się kroki, które musieliście podjąć, aby wprowadzić skrócenie słowników. +1 za wysiłek! – mhoff

2

Ta funkcja rekurencyjna pisałem ma coś prosisz o .. Można wybrać wcięcie, które chcesz,

def pretty(d, indent=0): 
    for key in sorted(d.keys()): 
     print '\t' * indent + str(key) 
     if isinstance(d[key], dict): 
      pretty(d[key], indent+1) 
     else: 
      print '\t' * (indent+1) + str(d[key]) 

Wyniki twojego słownika:

key_1 
    ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 'KU2FUGYB2U', 'JF3RQ315BY'] 
key_2 
    ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', '3Z89U7XM60', '167CYON6YN'] 
+1

Jeśli zmienisz ostatnią linię na "drukuj" \ t '* (wcięcie + 1) + str (d [klucz] [: 2]) + "..." to byłoby podobne do tego, co mam na myśli. Nie chcę całej listy. – CentAu

+0

O, kurcze, myślałem, że napisałeś ... bo nie chciałaś znowu pisać wszystkiego, moje nieporozumienie! –

6

można użyć modułu pprint:

pprint.pprint(obj) 

zwróci wynik:

{'key_1': ['EG8XYD9FVN', 
      'S2WARDCVAO', 
      'J00YCU55DP', 
      'R07BUIF2F7', 
      'VGPS1JD0UM', 
      'WL3TWSDP8E', 
      'LD8QY7DMJ3', 
      'J36U3Z9KOQ', 
      'KU2FUGYB2U', 
      'JF3RQ315BY'], 
'key_2': ['162LO154PM', 
      '3ROAV881V2', 
      'I4T79LP18J', 
      'WBD36EM6QL', 
      'DEIODVQU46', 
      'KWSJA5WDKQ', 
      'WX9SVRFO0G', 
      '6UN63WU64G', 
      '3Z89U7XM60', 
      '167CYON6YN']} 

I

wyjście
pprint.pprint(obj,depth=1) 

mogłoby:

{'key_1': [...], 'key_2': [...]} 

I

pprint.pprint(obj,compact=True) 

wyjście będzie:

{'key_1': ['EG8XYD9FVN', 'S2WARDCVAO', 'J00YCU55DP', 'R07BUIF2F7', 
      'VGPS1JD0UM', 'WL3TWSDP8E', 'LD8QY7DMJ3', 'J36U3Z9KOQ', 
      'KU2FUGYB2U', 'JF3RQ315BY'], 
'key_2': ['162LO154PM', '3ROAV881V2', 'I4T79LP18J', 'WBD36EM6QL', 
      'DEIODVQU46', 'KWSJA5WDKQ', 'WX9SVRFO0G', '6UN63WU64G', 
      '3Z89U7XM60', '167CYON6YN']} 
+0

'pprint.pprint (obj, depth = 1)' jest najbliższy temu, czego potrzebuję. Domyślam się, że nie ma wbudowanego sposobu drukowania tylko pierwszego elementu listy, a następnie "..." dla reszty. jak '{'key_': ['EG8XYD9FVN', ...]' – CentAu

2

Zastosowanie reprlib. Formatowanie nie jest ładne, ale w rzeczywistości jest skrócone.

> import repr 
> repr.repr(map(lambda _: range(100000), range(10))) 
'[[0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], [0, 1, 2, 3, 4, 5, ...], ...]' 
> repr.repr(dict(map(lambda i: (i, range(100000)), range(10)))) 
'{0: [0, 1, 2, 3, 4, 5, ...], 1: [0, 1, 2, 3, 4, 5, ...], 2: [0, 1, 2, 3, 4, 5, ...], 3: [0, 1, 2, 3, 4, 5, ...], ...}' 
+0

Tak. Część "skrót" lub zajmująca się strukturami rekursywnymi/samoczynnie się odwołującymi jest dokładnie tym, do czego została stworzona. Niestety nie jest oczywiste, jak połączyć to z ładnym drukiem (nowe linie, wcięcia, ...). –

4

Można użyć IPython.lib.pretty.

from IPython.lib.pretty import pprint 

> pprint(obj, max_seq_length=5) 
{'key_1': ['EG8XYD9FVN', 
    'S2WARDCVAO', 
    'J00YCU55DP', 
    'R07BUIF2F7', 
    'VGPS1JD0UM', 
    ...], 
'key_2': ['162LO154PM', 
    '3ROAV881V2', 
    'I4T79LP18J', 
    'WBD36EM6QL', 
    'DEIODVQU46', 
    ...]} 

> pprint(dict(map(lambda i: (i, range(i + 5)), range(100))), max_seq_length=10) 
{0: [0, 1, 2, 3, 4], 
1: [0, 1, 2, 3, 4, 5], 
2: [0, 1, 2, 3, 4, 5, 6], 
3: [0, 1, 2, 3, 4, 5, 6, 7], 
4: [0, 1, 2, 3, 4, 5, 6, 7, 8], 
5: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 
6: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 
7: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 
8: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 
9: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...], 
...} 

Dla starszych wersjach ipython, można wykorzystać RepresentationPrinter:

from IPython.lib.pretty import RepresentationPrinter 
import sys 

def compact_pprint(obj, max_seq_length=10): 
    printer = RepresentationPrinter(sys.stdout) 
    printer.max_seq_length = max_seq_length 
    printer.pretty(obj) 
    printer.flush() 
+0

Dlaczego upadek? – mhoff

+0

Prawdopodobnie dlatego, że w Internecie jest kilka szarpnięć – wordsforthewise