Programing

정렬 된 사전을 제대로 예쁘게 인쇄하는 방법은 없나요?

lottogame 2020. 9. 9. 18:55
반응형

정렬 된 사전을 제대로 예쁘게 인쇄하는 방법은 없나요?


저는 파이썬의 pprint 모듈을 좋아합니다. 테스트와 디버깅에 많이 사용합니다. 출력이 터미널 창에 잘 맞는지 확인하기 위해 너비 옵션을 자주 사용합니다.

Python 2.7 (내가 정말 좋아하는 또 다른 멋진 기능)에 새로운 정렬 된 사전 유형 을 추가 할 때까지 제대로 작동했습니다 . 정렬 된 사전을 예쁘게 인쇄하려고하면 제대로 표시되지 않습니다. 각 키-값 쌍을 고유 한 줄에 두는 대신 전체 내용이 한 줄에 표시되어 여러 번 줄 바꿈되어 읽기가 어렵습니다.

여기에있는 사람 중에 순서가 지정되지 않은 오래된 사전처럼 멋지게 인쇄 할 수있는 방법이 있습니까? 충분한 시간을 보내면 PrettyPrinter.format 메서드를 사용하여 뭔가 알아낼 수 있지만 여기에있는 누군가가 이미 해결책을 알고 있는지 궁금합니다.

업데이트 : 나는 이것에 대한 버그 보고서를 제출했습니다. http://bugs.python.org/issue10592 에서 볼 수 있습니다 .


임시 해결 방법으로 JSON 형식으로 덤프를 시도 할 수 있습니다. 일부 유형 정보를 잃어 버려도보기 좋고 순서를 유지합니다.

import json

pprint(data, indent=4)
# ^ugly

print(json.dumps(data, indent=4))
# ^nice

다음은 OrderedDict의 순서가 알파 정렬 인 경우 작동합니다. pprint는 인쇄 전에 사전을 정렬하기 때문입니다.

pprint(dict(o.items()))

pprint()내부적으로 stock 함수를 재정의하고 사용하여 작동하는 또 다른 답변이 있습니다 . 달리 내 일 이전됩니다 핸들 OrderedDict'등으로 다른 컨테이너의 내부에요 list또한 주어진 선택적인 키워드 인자를 처리 할 수 있어야합니다 - 그러나 그것은 다른 하나는 여유있는 출력 제어의 동일한 학위를 소지하지 않습니다.

stock 함수의 출력을 임시 버퍼로 리디렉션 한 다음 출력 스트림으로 보내기 전에 워드 랩핑합니다. 생성 된 최종 결과물은 예외적으로 예쁘지는 않지만 괜찮으며 해결 방법으로 사용하기에 "충분"할 수 있습니다.

2.0 업데이트

표준 라이브러리 textwrap모듈 을 사용하여 단순화되고 Python 2 및 3에서 모두 작동하도록 수정되었습니다.

from collections import OrderedDict
try:
    from cStringIO import StringIO
except ImportError:  # Python 3
    from io import StringIO
from pprint import pprint as pp_pprint
import sys
import textwrap

def pprint(object, **kwrds):
    try:
        width = kwrds['width']
    except KeyError: # unlimited, use stock function
        pp_pprint(object, **kwrds)
        return
    buffer = StringIO()
    stream = kwrds.get('stream', sys.stdout)
    kwrds.update({'stream': buffer})
    pp_pprint(object, **kwrds)
    words = buffer.getvalue().split()
    buffer.close()

    # word wrap output onto multiple lines <= width characters
    try:
        print >> stream, textwrap.fill(' '.join(words), width=width)
    except TypeError:  # Python 3
        print(textwrap.fill(' '.join(words), width=width), file=stream)

d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
lod = [OrderedDict((('john',1), ('paul',2), ('mary',3))),
       OrderedDict((('moe',1), ('curly',2), ('larry',3))),
       OrderedDict((('weapons',1), ('mass',2), ('destruction',3)))]

샘플 출력 :

pprint(d, width=40)

»   {'john': 1, 'mary': 3, 'paul': 2}

pprint(od, width=40)

» OrderedDict([('john', 1), ('paul', 2),
   ('mary', 3)])

pprint(lod, width=40)

» [OrderedDict([('john', 1), ('paul', 2),
   ('mary', 3)]), OrderedDict([('moe', 1),
   ('curly', 2), ('larry', 3)]),
   OrderedDict([('weapons', 1), ('mass',
   2), ('destruction', 3)])]


정렬 된 사전을 인쇄하려면, 예 :

from collections import OrderedDict

d=OrderedDict([
    ('a', OrderedDict([
        ('a1',1),
        ('a2','sss')
    ])),
    ('b', OrderedDict([
        ('b1', OrderedDict([
            ('bb1',1),
            ('bb2',4.5)])),
        ('b2',4.5)
    ])),
])

나는한다

def dict_or_OrdDict_to_formatted_str(OD, mode='dict', s="", indent=' '*4, level=0):
    def is_number(s):
        try:
            float(s)
            return True
        except ValueError:
            return False
    def fstr(s):
        return s if is_number(s) else '"%s"'%s
    if mode != 'dict':
        kv_tpl = '("%s", %s)'
        ST = 'OrderedDict([\n'; END = '])'
    else:
        kv_tpl = '"%s": %s'
        ST = '{\n'; END = '}'
    for i,k in enumerate(OD.keys()):
        if type(OD[k]) in [dict, OrderedDict]:
            level += 1
            s += (level-1)*indent+kv_tpl%(k,ST+dict_or_OrdDict_to_formatted_str(OD[k], mode=mode, indent=indent, level=level)+(level-1)*indent+END)
            level -= 1
        else:
            s += level*indent+kv_tpl%(k,fstr(OD[k]))
        if i!=len(OD)-1:
            s += ","
        s += "\n"
    return s

print dict_or_OrdDict_to_formatted_str(d)

어느 양보

"a": {
    "a1": 1,
    "a2": "sss"
},
"b": {
    "b1": {
        "bb1": 1,
        "bb2": 4.5
    },
    "b2": 4.5
}

또는

print dict_or_OrdDict_to_formatted_str(d, mode='OD')

어느 양보

("a", OrderedDict([
    ("a1", 1),
    ("a2", "sss")
])),
("b", OrderedDict([
    ("b1", OrderedDict([
        ("bb1", 1),
        ("bb2", 4.5)
    ])),
    ("b2", 4.5)
]))

.NET Framework 구현을 해킹하는 방법은 다음과 같습니다 pprint. pprint인쇄하기 전에 키를 정렬하므로 순서를 유지하려면 원하는 방식으로 키를 정렬하면됩니다.

이는 items()기능에 영향을 미칩니다 . 따라서 pprint를 수행 한 후 재정의 된 함수를 보존하고 복원 할 수 있습니다.

from collections import OrderedDict
import pprint

class ItemKey(object):
  def __init__(self, name, position):
    self.name = name
    self.position = position
  def __cmp__(self, b):
    assert isinstance(b, ItemKey)
    return cmp(self.position, b.position)
  def __repr__(self):
    return repr(self.name)

OrderedDict.items = lambda self: [
    (ItemKey(name, i), value)
    for i, (name, value) in enumerate(self.iteritems())]
OrderedDict.__repr__ = dict.__repr__

a = OrderedDict()
a[4] = '4'
a[1] = '1'
a[2] = '2'
print pprint.pformat(a) # {4: '4', 1: '1', 2: '2'}

이것은 매우 조잡하지만 임의의 Mappings 및 Iterables로 구성된 데이터 구조를 시각화하는 방법이 필요했고 이것이 포기하기 전에 생각해 낸 것입니다. 재귀 적이므로 중첩 된 구조와 목록을 통과합니다. 컬렉션의 Mapping 및 Iterable 추상 기본 클래스를 사용하여 거의 모든 것을 처리했습니다.

나는 간결한 파이썬 코드로 출력과 같은 거의 yaml을 목표로했지만 제대로 만들지 못했습니다.

def format_structure(d, level=0):
    x = ""
    if isinstance(d, Mapping):
        lenk = max(map(lambda x: len(str(x)), d.keys()))
        for k, v in d.items():
            key_text = "\n" + " "*level + " "*(lenk - len(str(k))) + str(k)
            x += key_text + ": " + format_structure(v, level=level+lenk)
    elif isinstance(d, Iterable) and not isinstance(d, basestring):
        for e in d:
            x += "\n" + " "*level + "- " + format_structure(e, level=level+4)
    else:
        x = str(d)
    return x

OrderedDict 및 OrderedDict 목록을 사용하는 일부 테스트 데이터 ... (sheesh Python에는 OrderedDict 리터럴이 너무 많이 필요합니다 ...)

d = OrderedDict([("main",
                  OrderedDict([("window",
                                OrderedDict([("size", [500, 500]),
                                             ("position", [100, 900])])),
                               ("splash_enabled", True),
                               ("theme", "Dark")])),
                 ("updates",
                  OrderedDict([("automatic", True),
                               ("servers",
                                [OrderedDict([("url", "http://server1.com"),
                                              ("name", "Stable")]),
                                 OrderedDict([("url", "http://server2.com"),
                                              ("name", "Beta")]),
                                 OrderedDict([("url", "http://server3.com"),
                                              ("name", "Dev")])]),
                               ("prompt_restart", True)])),
                 ("logging",
                  OrderedDict([("enabled", True),
                               ("rotate", True)]))])

print format_structure(d)

다음 출력을 생성합니다.

   main: 
               window: 
                         size: 
                             - 500
                             - 500
                     position: 
                             - 100
                             - 900
       splash_enabled: True
                theme: Dark
updates: 
            automatic: True
              servers: 
                     - 
                          url: http://server1.com
                         name: Stable
                     - 
                          url: http://server2.com
                         name: Beta
                     - 
                          url: http://server3.com
                         name: Dev
       prompt_restart: True
logging: 
       enabled: True
        rotate: True

더 나은 정렬을 위해 str.format ()을 사용하는 방법에 대해 약간의 생각이 있었지만 파고 들고 싶지는 않았습니다. 원하는 정렬 유형에 따라 필드 너비를 동적으로 지정해야하므로 까다 롭거나 번거로울 수 있습니다.

어쨌든, 이것은 읽을 수있는 계층 적 방식으로 내 데이터를 보여 주므로 저에게 효과적입니다!


def pprint_od(od):
    print "{"
    for key in od:
        print "%s:%s,\n" % (key, od[key]) # Fixed syntax
    print "}"

됐습니다 ^^

for item in li:
    pprint_od(item)

또는

(pprint_od(item) for item in li)

나는이 부정한 원숭이 패치 기반 해킹을 python3.5에서 테스트했으며 작동합니다.

pprint.PrettyPrinter._dispatch[pprint._collections.OrderedDict.__repr__] = pprint.PrettyPrinter._pprint_dict


def unsorted_pprint(data):
    def fake_sort(*args, **kwargs):
        return args[0]
    orig_sorted = __builtins__.sorted
    try:
        __builtins__.sorted = fake_sort
        pprint.pprint(data)
    finally:
        __builtins__.sorted = orig_sorted

pprint일반적인 dict 기반 요약 사용하고 실제로 인쇄를 위해 키가 정렬되지 않도록 호출 기간 동안 정렬을 비활성화합니다.


The pprint() method is just invoking the __repr__() method of things in it, and OrderedDict doesn't appear to do much in it's method (or doesn't have one or something).

Here's a cheap solution that should work IF YOU DON'T CARE ABOUT THE ORDER BEING VISIBLE IN THE PPRINT OUTPUT, which may be a big if:

class PrintableOrderedDict(OrderedDict):
    def __repr__(self):
        return dict.__repr__(self)

I'm actually surprised that the order isn't preserved... ah well.


You can also use this simplification of the kzh answer:

pprint(data.items(), indent=4)

It preserves the order and will output almost the same than the webwurst answer (print through json dump).


Here is my approach to pretty print an OrderedDict

from collections import OrderedDict
import json
d = OrderedDict()
d['duck'] = 'alive'
d['parrot'] = 'dead'
d['penguin'] = 'exploded'
d['Falcon'] = 'discharged'
print(d)
print(json.dumps(d,indent=4))

OutPut:

OrderedDict([('duck', 'alive'), ('parrot', 'dead'), ('penguin', 'exploded'), ('Falcon', 'discharged')])

{
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded",
    "Falcon": "discharged"
}

If you want to pretty print dictionary with keys in sorted order

print(json.dumps(indent=4,sort_keys=True))
{
    "Falcon": "discharged",
    "duck": "alive",
    "parrot": "dead",
    "penguin": "exploded"
}

You could redefine pprint() and intercept calls for OrderedDict's. Here's a simple illustration. As written, the OrderedDict override code ignores any optional stream, indent, width, or depth keywords that may have been passed, but could be enhanced to implement them. Unfortunately this technique doesn't handle them inside another container, such as a list of OrderDict's

from collections import OrderedDict
from pprint import pprint as pp_pprint

def pprint(obj, *args, **kwrds):
    if not isinstance(obj, OrderedDict):
        # use stock function
        return pp_pprint(obj, *args, **kwrds)
    else:
        # very simple sample custom implementation...
        print "{"
        for key in obj:
            print "    %r:%r" % (key, obj[key])
        print "}"

l = [10, 2, 4]
d = dict((('john',1), ('paul',2), ('mary',3)))
od = OrderedDict((('john',1), ('paul',2), ('mary',3)))
pprint(l, width=4)
# [10,
#  2,
#  4]
pprint(d)
# {'john': 1, 'mary': 3, 'paul': 2}

pprint(od)
# {
#     'john':1
#     'paul':2
#     'mary':3
# }

If the dictionary items are all of one type, you could use the amazing data-handling library pandas:

>>> import pandas as pd
>>> x = {'foo':1, 'bar':2}
>>> pd.Series(x)
bar    2
foo    1
dtype: int64

or

>>> import pandas as pd
>>> x = {'foo':'bar', 'baz':'bam'}
>>> pd.Series(x)
baz    bam
foo    bar
dtype: object

참고URL : https://stackoverflow.com/questions/4301069/any-way-to-properly-pretty-print-ordered-dictionaries

반응형