จะพิมพ์พจนานุกรมที่ซ้อนกันได้อย่างไร


289

ฉันจะพิมพ์พจนานุกรมที่มีความลึก ~ 4 ใน Python ได้อย่างไร ฉันลองพิมพ์ด้วยสวยpprint()แต่ไม่ได้ผล:

import pprint 
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(mydict)

ฉันแค่ต้องการเยื้อง ( "\t") สำหรับการทำรังแต่ละครั้งเพื่อให้ฉันได้รับสิ่งนี้:

key1
    value1
    value2
    key2
       value1
       value2

เป็นต้น

ฉันจะทำสิ่งนี้ได้อย่างไร


29
"ไม่ทำงาน" หมายถึงอะไร โปรดระบุอย่างแม่นยำว่า pprint "ใช้งานไม่ได้" อย่างไร
S.Lott

5
ตอนนี้ฉันใช้คำตอบเหล่านี้ 3 ข้อ (แต่ละข้อในสถานการณ์เฉพาะ): @ คำตอบของ json ของ jsonนั้นดี แต่บางครั้งก็ล้มเหลวเมื่อวัตถุไม่สามารถ json ต่อเนื่องได้ (ข้อยกเว้น) ถ้าคำตอบ json ของ @ Ken ไม่ได้ผลให้ลองใช้คำตอบ yaml ของ Andyและควรใช้งานได้ แต่เอาต์พุตสตริงนั้นอ่านได้น้อยกว่ามนุษย์ [คำตอบของ @ sth] เป็นคำทั่วไปมากที่สุด (ควรใช้กับวัตถุใด ๆ และไม่ใช้ libs ใด ๆ )
เทรเวอร์บอยด์สมิ ธ

คำตอบ:


143

ฉันไม่แน่ใจว่าคุณต้องการให้การจัดรูปแบบเป็นอย่างไร แต่คุณสามารถเริ่มต้นด้วยฟังก์ชันดังนี้:

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

8
คุณรู้หรือไม่ว่าคำตอบทั่วไปของเคนดีกว่านี้มาก Json จัดการทุกอย่างเรียบร้อยแล้วและสิ่งนี้อาจทำให้เกิดข้อผิดพลาดเช่น: UnicodeEncodeError: 'ascii' codec ไม่สามารถเข้ารหัสอักขระ u '\ xf3' ในตำแหน่ง 50: ลำดับไม่อยู่ในช่วง (128)
แปลกใจที่

ฉันไม่สามารถใช้งานได้กับ dict ที่ซ้อนกันของโซลูชันของฉันเพราะมันให้ UnicodeEncodeError ให้ฉันมันยังไม่พิมพ์คีย์ dict ไม่เข้าไปในรายการและ tuples และไม่เก็บไวยากรณ์ที่ถูกต้องของหลาม
y.petremann

คำตอบนี้ทำงานได้อย่างมีเสน่ห์สำหรับฉัน แต่ฉันโพสต์คำถามใหม่stackoverflow.com/questions/36972225/ …ซึ่งกำหนดขีด จำกัด ว่าควรพิมพ์ค่าจำนวนเท่าใด
gsamaras

ใช้ได้ดีทีเดียว. หากคุณมีรายการซ้อนอยู่ในคำถามของ OP คุณจะต้องเพิ่มการจัดการบางอย่าง หากคุณมีปัญหาใน Py2 สาเหตุก็คือมันไม่สามารถจัดการ Unicode ได้อย่างถูกต้องโดยไม่มีแฮ็คแบบ__future__ที่คำตอบกล่าวถึงในตอนนี้ดังนั้นคุณต้องจ้างสิ่งที่ต้องการ (หรืออัปเดตเป็น 3 แล้ว)
sudo

สิ่งนี้ทำงานได้ดีพอสำหรับฉัน: python def pretty(d, indent=0): for key, value in d.items(): if isinstance(value, dict): print(' ' * indent + str(key)) pretty(value, indent+1) else: print(' ' * (indent+1) + f"{key}: {value}")
hum3

500

ความคิดแรกของฉันคือ JSON serializer นั้นค่อนข้างดีในพจนานุกรมที่ซ้อนกันดังนั้นฉันจึงโกงและใช้สิ่งนั้น:

>>> import json
>>> print json.dumps({'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}},
...                  sort_keys=True, indent=4)
{
    "a": 2,
    "b": {
        "x": 3,
        "y": {
            "t1": 4,
            "t2": 5
        }
    }
}

41
นี่มันเจ๋ง แต่ก็พิมพ์พจนานุกรมไม่ได้เลย พิมพ์ json.dumps (myObject .__ dict__, sort_keys = True, เยื้อง = 4) #TypeError: <object ที่ 0x0000000002E6A748> ไม่ใช่ JSON ต่อเนื่อง
tponthieux

4
แม้ว่าสิ่งนี้จะมีประโยชน์ แต่ผลลัพธ์ไม่ใช่สิ่งที่ OP ต้องการ
martineau

2
@martineau: ผลลัพธ์ที่ร้องขอของ OP ไม่สมเหตุสมผลพจนานุกรมต้องการคีย์ต่อค่า
naught101

2
@ naught101: เครื่องพิมพ์สวยสามารถทำสิ่งที่จำเป็นในการผลิตผลลัพธ์ที่ต้องการ
martineau

22
json.dumps ต้องใช้ฟังก์ชั่นการแปลงเป็นอาร์กิวเมนต์ตัวเลือกให้กับ json.dumps (myObject .__ dict__, sort_keys = True เยื้อง = 4, deault = STR) อย่างน้อยคุณสามารถใช้วัตถุการดำเนินงานของReprในการพิมพ์ตัวเองและได้รับรอบ TypeError ที่ไม่ต่อเนื่องกันของ JSON
RFairey

56

คุณอาจจะลองYAMLผ่านPyYAML สามารถปรับเอาต์พุตของมันได้ ฉันขอแนะนำให้เริ่มต้นด้วยสิ่งต่อไปนี้:

print yaml.dump(data, allow_unicode=True, default_flow_style=False)

ผลลัพธ์สามารถอ่านได้มาก สามารถแยกวิเคราะห์กลับไปยัง Python ได้หากต้องการ

แก้ไข:

ตัวอย่าง:

>>> import yaml
>>> data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> print yaml.dump(data, default_flow_style=False)
a: 2
b:
  x: 3
  y:
    t1: 4
    t2: 5

1
การใช้ yaml นั้นน่าสนใจมากเพราะมันเก็บข้อมูลไว้ในรูปแบบของมันสิ่งเดียวที่ฉันพูดได้ก็คือมันไม่ได้ผลิตสตริงไพ ธ อนที่ถูกต้อง แต่สามารถแปลงกลับเป็นไพ ธ อนได้
y.petremann

1
yaml ไม่ชอบประเภทสเกลาร์เวอร์ชันของ Numpy ... ฉันไม่แปลกใจที่ไม่รองรับอาร์เรย์ numpy แต่ฉันคาดว่าจะมีเอาต์พุตเดียวกันสำหรับ a floatและ anumpy.float64
PhilMacKay

วิธีการนี้ใช้ได้ผลกับฉันด้วยรายการพจนานุกรม
Grant Shannon

36

จากสิ่งที่ได้ทำไปแล้วฉันไม่เห็นเครื่องพิมพ์สวย ๆ ที่อย่างน้อยเลียนแบบเอาท์พุทของหลามล่ามด้วยการจัดรูปแบบที่ง่ายมากดังนั้นนี่คือของฉัน:

class Formatter(object):
    def __init__(self):
        self.types = {}
        self.htchar = '\t'
        self.lfchar = '\n'
        self.indent = 0
        self.set_formater(object, self.__class__.format_object)
        self.set_formater(dict, self.__class__.format_dict)
        self.set_formater(list, self.__class__.format_list)
        self.set_formater(tuple, self.__class__.format_tuple)

    def set_formater(self, obj, callback):
        self.types[obj] = callback

    def __call__(self, value, **args):
        for key in args:
            setattr(self, key, args[key])
        formater = self.types[type(value) if type(value) in self.types else object]
        return formater(self, value, self.indent)

    def format_object(self, value, indent):
        return repr(value)

    def format_dict(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + repr(key) + ': ' +
            (self.types[type(value[key]) if type(value[key]) in self.types else object])(self, value[key], indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_list(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + self.lfchar + self.htchar * indent)

    def format_tuple(self, value, indent):
        items = [
            self.lfchar + self.htchar * (indent + 1) + (self.types[type(item) if type(item) in self.types else object])(self, item, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + self.lfchar + self.htchar * indent)

ในการเริ่มต้น:

pretty = Formatter()

มันสามารถรองรับการเพิ่มตัวจัดรูปแบบสำหรับชนิดที่กำหนดคุณเพียงแค่ต้องสร้างฟังก์ชันสำหรับสิ่งนี้และผูกกับประเภทที่คุณต้องการด้วย set_formater:

from collections import OrderedDict

def format_ordereddict(self, value, indent):
    items = [
        self.lfchar + self.htchar * (indent + 1) +
        "(" + repr(key) + ', ' + (self.types[
            type(value[key]) if type(value[key]) in self.types else object
        ])(self, value[key], indent + 1) + ")"
        for key in value
    ]
    return 'OrderedDict([%s])' % (','.join(items) +
           self.lfchar + self.htchar * indent)
pretty.set_formater(OrderedDict, format_ordereddict)

ด้วยเหตุผลทางประวัติศาสตร์ฉันเก็บเครื่องพิมพ์สวยไว้ก่อนหน้านี้ซึ่งเป็นฟังก์ชั่นแทนที่จะเป็นคลาส แต่พวกเขาทั้งสองสามารถใช้วิธีเดียวกันรุ่นคลาสก็อนุญาตได้มากขึ้น:

def pretty(value, htchar='\t', lfchar='\n', indent=0):
    nlch = lfchar + htchar * (indent + 1)
    if type(value) is dict:
        items = [
            nlch + repr(key) + ': ' + pretty(value[key], htchar, lfchar, indent + 1)
            for key in value
        ]
        return '{%s}' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is list:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '[%s]' % (','.join(items) + lfchar + htchar * indent)
    elif type(value) is tuple:
        items = [
            nlch + pretty(item, htchar, lfchar, indent + 1)
            for item in value
        ]
        return '(%s)' % (','.join(items) + lfchar + htchar * indent)
    else:
        return repr(value)

วิธีใช้:

>>> a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':pretty,'unicode':u'\xa7',("tuple","key"):"valid"}
>>> a
{'function': <function pretty at 0x7fdf555809b0>, 'tuple': ('a', 'b', 1, 2), 'list': ['a', 'b', 1, 2], 'dict': {'a': 1, 2: 'b'}, 'unicode': u'\xa7', ('tuple', 'key'): 'valid'}
>>> print(pretty(a))
{
    'function': <function pretty at 0x7fdf555809b0>,
    'tuple': (
        'a',
        'b',
        1,
        2
    ),
    'list': [
        'a',
        'b',
        1,
        2
    ],
    'dict': {
        'a': 1,
        2: 'b'
    },
    'unicode': u'\xa7',
    ('tuple', 'key'): 'valid'
}

เปรียบเทียบกับรุ่นอื่น:

  • โซลูชันนี้จะค้นหาประเภทวัตถุโดยตรงดังนั้นคุณสามารถพิมพ์ได้เกือบทุกอย่างไม่เพียง แต่รายการหรือ dict
  • ไม่มีการพึ่งพาใด ๆ
  • ทุกอย่างถูกใส่ไว้ในสตริงดังนั้นคุณสามารถทำสิ่งที่คุณต้องการได้
  • คลาสและฟังก์ชันได้รับการทดสอบและใช้งานได้กับ Python 2.7 และ 3.4
  • คุณสามารถมีวัตถุทุกชนิดที่อยู่ภายในนี่คือการแสดงของพวกเขาและไม่ใช่เนื้อหาของพวกเขาที่ถูกวางในผลลัพธ์ (ดังนั้นสตริงมีคำพูดสตริง Unicode จะถูกแสดงอย่างเต็มที่ ... )
  • ด้วยเวอร์ชันคลาสคุณสามารถเพิ่มการจัดรูปแบบสำหรับวัตถุทุกประเภทที่คุณต้องการหรือเปลี่ยนเป็นประเภทที่กำหนดไว้แล้ว
  • คีย์สามารถเป็นประเภทที่ถูกต้องใด ๆ
  • สามารถเปลี่ยนเยื้องและอักขระขึ้นบรรทัดใหม่สำหรับทุกสิ่งที่เราต้องการ
  • Dict, List และ Tuples นั้นถูกพิมพ์ออกมาสวย

2
นี่ควรเป็นทางออกที่ยอมรับได้แน่นอน - การขาดการพึ่งพา JSON นั้นใหญ่มาก
Josh

มันจะเจ๋งถ้ามันสามารถทำวัตถุโดยแปลงให้เป็น dicts และตั้งค่าคีย์ของพวกเขาให้เป็นประเภทของวัตถุ
Alex Cory

โดยทั่วไปคุณสามารถแทนที่เมธอด format_object internaly หรือ externaly เพื่อทำเช่นนั้นได้
y.petremann

set_formater - ต้องการสอง t นี่เป็นตัวพิมพ์ควรเป็น formatter
Nikolay Prokopyev

32

ด้วยวิธีนี้คุณสามารถพิมพ์ได้อย่างน่าสนใจตัวอย่างชื่อพจนานุกรมของคุณคือสินธุ์

import json

print (json.dumps(yasin, indent=2))

5
สิ่งนี้จะถือว่าเนื้อหาของพจนานุกรมนั้นเป็น json ซึ่งทำให้เป็นอนุกรมได้ซึ่งไม่จำเป็นต้องเป็นจริง
SpiXel

8

ตัวเลือกอื่นด้วยyapf:

from pprint import pformat
from yapf.yapflib.yapf_api import FormatCode

dict_example = {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5], '4': {'1': '1', '2': '2', '3': [1, 2, 3, 4, 5]}}
dict_string = pformat(dict_example)
formatted_code, _ = FormatCode(dict_string)

print(formatted_code)

เอาท์พุท:

{
    '1': '1',
    '2': '2',
    '3': [1, 2, 3, 4, 5],
    '4': {
        '1': '1',
        '2': '2',
        '3': [1, 2, 3, 4, 5]
    }
}

5

ในขณะที่คนอื่นโพสต์คุณสามารถใช้การเรียกซ้ำ / dfs เพื่อพิมพ์ข้อมูลพจนานุกรมที่ซ้อนกันและโทรซ้ำถ้ามันเป็นพจนานุกรม มิฉะนั้นพิมพ์ข้อมูล

def print_json(data):
    if type(data) == dict:
            for k, v in data.items():
                    print k
                    print_json(v)
    else:
            print data

5

วิธี pythonic ที่ดีที่สุดวิธีหนึ่งคือการใช้โมดูลpprint ที่สร้างไว้แล้ว

อาร์กิวเมนต์ที่คุณต้องการกำหนดความลึกของการพิมพ์เป็นไปตามที่คุณคาดหวัง depth

import pprint
pp = pprint.PrettyPrinter(depth=4)
pp.pprint(mydict)

แค่นั้นแหละ !


4

poutสามารถพิมพ์สิ่งใดก็ได้ที่คุณทิ้งไว้เช่น (ยืมdataจากคำตอบอื่น):

data = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
pout.vs(data)

จะส่งผลให้พิมพ์ออกไปยังหน้าจอเช่น:

{
    'a': 2,
    'b':
    {
        'y':
        {
            't2': 5,
            't1': 4
        },
        'x': 3
    }
}

หรือคุณสามารถคืนค่าเอาท์พุทสตริงที่จัดรูปแบบของวัตถุของคุณ:

v = pout.s(data)

กรณีการใช้งานหลักมีไว้สำหรับการดีบักดังนั้นมันจึงไม่สำลักกับอินสแตนซ์ของวัตถุหรืออะไรก็ตามและมันจะจัดการยูนิทเอาท์พุทอย่างที่คุณคาดไว้ใช้งานได้ใน python 2.7 และ 3

การเปิดเผย : ฉันเป็นผู้เขียนและผู้ดูแลของมุ่ย


3

ฉันตอบคำถามของ sthและแก้ไขมันเล็กน้อยเพื่อให้เหมาะกับความต้องการของพจนานุกรมและรายการที่ซ้อนกัน:

def pretty(d, indent=0):
    if isinstance(d, dict):
        for key, value in d.iteritems():
            print '\t' * indent + str(key)
            if isinstance(value, dict) or isinstance(value, list):
                pretty(value, indent+1)
            else:
                print '\t' * (indent+1) + str(value)
    elif isinstance(d, list):
        for item in d:
            if isinstance(item, dict) or isinstance(item, list):
                pretty(item, indent+1)
            else:
                print '\t' * (indent+1) + str(item)
    else:
        pass

ซึ่งให้ผลลัพธ์เช่น:

>>> 
xs:schema
    @xmlns:xs
        http://www.w3.org/2001/XMLSchema
    xs:redefine
        @schemaLocation
            base.xsd
        xs:complexType
            @name
                Extension
            xs:complexContent
                xs:restriction
                    @base
                        Extension
                    xs:sequence
                        xs:element
                            @name
                                Policy
                            @minOccurs
                                1
                            xs:complexType
                                xs:sequence
                                    xs:element
                                            ...

1

Sth ฉันจมนั่นน่ารัก;)

def pretty(d, indent=0):
    for key, value in d.iteritems():
        if isinstance(value, dict):
            print '\t' * indent + (("%30s: {\n") % str(key).upper())
            pretty(value, indent+1)
            print '\t' * indent + ' ' * 32 + ('} # end of %s #\n' % str(key).upper())
        elif isinstance(value, list):
            for val in value:
                print '\t' * indent + (("%30s: [\n") % str(key).upper())
                pretty(val, indent+1)
                print '\t' * indent + ' ' * 32 + ('] # end of %s #\n' % str(key).upper())
        else:
            print '\t' * indent + (("%30s: %s") % (str(key).upper(),str(value)))

1
-1: ไม่ได้จัดการกับlistค่าที่ไม่ได้เป็นdictกรณีเช่น==>pretty({'key': [1, 2, 3]}, indent=4) AttributeError: 'int' object has no attribute 'iteritems'ฉันไม่ชอบแป้นตัวพิมพ์ใหญ่
martineau

วิธีแก้ปัญหาของคุณพิจารณาว่าไม่มี dict ภายในรายการภายใน dict หลัก นอกจากนี้ยังพิจารณาว่าเราไม่ต้องการพิมพ์รายการหรือสิ่งอันดับ สุดท้ายอย่าใช้ตัวพิมพ์ใหญ่สำหรับคีย์ผลลัพธ์สำหรับ {'a': 0, 'A': 1} จะไม่ถูกต้อง
y.petremann

1
This class prints out a complex nested dictionary with sub dictionaries and sub lists.  
##
## Recursive class to parse and print complex nested dictionary
##

class NestedDictionary(object):
    def __init__(self,value):
        self.value=value

    def print(self,depth):
        spacer="--------------------"
        if type(self.value)==type(dict()):
            for kk, vv in self.value.items():
                if (type(vv)==type(dict())):
                    print(spacer[:depth],kk)
                    vvv=(NestedDictionary(vv))
                    depth=depth+3
                    vvv.print(depth)
                    depth=depth-3
                else:
                    if (type(vv)==type(list())):
                        for i in vv:
                            vvv=(NestedDictionary(i))
                            depth=depth+3
                            vvv.print(depth)
                            depth=depth-3
                    else:
                        print(spacer[:depth],kk,vv) 

##
## Instatiate and execute - this prints complex nested dictionaries
## with sub dictionaries and sub lists
## 'something' is a complex nested dictionary

MyNest=NestedDictionary(weather_com_result)
MyNest.print(0)

1

ฉันเขียนโค้ดง่าย ๆ นี้เพื่อพิมพ์โครงสร้างทั่วไปของวัตถุ json ใน Python

def getstructure(data, tab = 0):
    if type(data) is dict:
        print ' '*tab + '{' 
        for key in data:
            print ' '*tab + '  ' + key + ':'
            getstructure(data[key], tab+4)
        print ' '*tab + '}'         
    elif type(data) is list and len(data) > 0:
        print ' '*tab + '['
        getstructure(data[0], tab+4)
        print ' '*tab + '  ...'
        print ' '*tab + ']'

ผลลัพธ์สำหรับข้อมูลต่อไปนี้

a = {'list':['a','b',1,2],'dict':{'a':1,2:'b'},'tuple':('a','b',1,2),'function':'p','unicode':u'\xa7',("tuple","key"):"valid"}
getstructure(a)

มีขนาดเล็กมากและมีลักษณะดังนี้:

{
  function:
  tuple:
  list:
    [
      ...
    ]
  dict:
    {
      a:
      2:
    }
  unicode:
  ('tuple', 'key'):
}

0

ฉันเป็นงูหลามตัวใหม่ที่เพิ่งเข้าร่วมตัวเอง แต่ฉันทำงานกับพจนานุกรมที่ซ้อนกันในช่วงสองสามสัปดาห์ที่ผ่านมาและนี่คือสิ่งที่ฉันคิดขึ้นมา

คุณควรลองใช้สแต็ก ทำคีย์จากพจนานุกรมรูทลงในรายการของรายการ:

stack = [ root.keys() ]     # Result: [ [root keys] ]

ไปในลำดับที่กลับมาจากครั้งแรกไปที่ค้นหาคีย์แต่ละรายการในพจนานุกรมเพื่อดูว่าค่าของมันคือ (เช่น) พจนานุกรม หากไม่พิมพ์รหัสก็จะลบออก อย่างไรก็ตามหากค่าของคีย์คือพจนานุกรมให้พิมพ์คีย์จากนั้นผนวกคีย์สำหรับค่านั้นไปยังจุดสิ้นสุดของสแต็กและเริ่มต้นการประมวลผลรายการนั้นด้วยวิธีเดียวกันโดยทำซ้ำสำหรับรายการคีย์ใหม่ซ้ำ

หากค่าสำหรับคีย์ที่สองในแต่ละรายการเป็นพจนานุกรมคุณจะมีสิ่งนี้หลังจากผ่านหลายรอบ:

[['key 1','key 2'],['key 2.1','key 2.2'],['key 2.2.1','key 2.2.2'],[`etc.`]]

ข้อดีของวิธีนี้คือเยื้องนั้น\tมีความยาวเท่าของความยาวของสแต็ก:

indent = "\t" * len(stack)

ข้อเสียคือในการที่จะตรวจสอบแต่ละคีย์คุณจะต้องแฮชไปยังพจนานุกรมย่อยที่เกี่ยวข้องแม้ว่าจะสามารถจัดการได้อย่างง่ายดายด้วยรายการความเข้าใจและง่าย forลูปแบบ :

path = [li[-1] for li in stack]
# The last key of every list of keys in the stack

sub = root
for p in path:
    sub = sub[p]


if type(sub) == dict:
    stack.append(sub.keys()) # And so on

โปรดทราบว่าวิธีการนี้จะทำให้คุณต้องล้างข้อมูลรายการว่างเปล่าและเพื่อลบคีย์สุดท้ายในรายการใด ๆ ตามด้วยรายการว่าง (ซึ่งแน่นอนว่าอาจสร้างรายการว่างอื่นและอื่น ๆ )

มีวิธีอื่น ๆ ในการใช้วิธีนี้ แต่หวังว่านี่จะช่วยให้คุณมีความคิดพื้นฐานเกี่ยวกับวิธีการทำ

แก้ไข: หากคุณไม่ต้องการดำเนินการทั้งหมดpprintโมดูลจะพิมพ์พจนานุกรมที่ซ้อนกันในรูปแบบที่ดี


0

นี่คือฟังก์ชันที่ฉันเขียนตามความคิดเห็นของ sth มันทำงานเหมือนกับ json.dumps กับเยื้อง แต่ฉันใช้แท็บแทนการเว้นวรรคสำหรับเยื้อง ใน Python 3.2+ คุณสามารถระบุการเยื้องเป็น '\ t' โดยตรง แต่ไม่ใช่ใน 2.7

def pretty_dict(d):
    def pretty(d, indent):
        for i, (key, value) in enumerate(d.iteritems()):
            if isinstance(value, dict):
                print '{0}"{1}": {{'.format( '\t' * indent, str(key))
                pretty(value, indent+1)
                if i == len(d)-1:
                    print '{0}}}'.format( '\t' * indent)
                else:
                    print '{0}}},'.format( '\t' * indent)
            else:
                if i == len(d)-1:
                    print '{0}"{1}": "{2}"'.format( '\t' * indent, str(key), value)
                else:
                    print '{0}"{1}": "{2}",'.format( '\t' * indent, str(key), value)
    print '{'
    pretty(d,indent=1)
    print '}'

Ex:

>>> dict_var = {'a':2, 'b':{'x':3, 'y':{'t1': 4, 't2':5}}}
>>> pretty_dict(dict_var)
{
    "a": "2",
    "b": {
        "y": {
            "t2": "5",
            "t1": "4"
        },
        "x": "3"
    }
}

ฉันไม่สามารถใช้งานได้กับคำสั่งที่ซ้อนกันของโซลูชันของฉันเพราะมันให้ UnicodeEncodeError ของฉันเช่นกันรายการและคีย์ทั้งหมดจะถูกแปลงเป็นสตริงจะเกิดอะไรขึ้นถ้าเราใช้ตัวเลขหรือสิ่งอันดับที่มีรายการและ dicts Finnaly โซลูชันของคุณคำนึงถึงว่าวัตถุของเราที่เราต้องการให้พิมพ์สวยต้องเป็น dict
y.petremann

ฉันไม่ได้พยายามเขียนฟังก์ชั่นการพิมพ์ทั่วไปสำหรับ pict dython ความคิดเห็นที่ได้คะแนนสูงสุดแล้วแสดงให้เห็นถึงวิธีการพิมพ์พจน์ การมีส่วนร่วมของฉันคือการเขียนทางเลือกเพื่อ json.dumps ด้วย '\ t' เพื่อเยื้องแทนแท็บใน python 2.7
Al Conrad

ฉันเห็นด้วยกับคุณเกี่ยวกับการเขียนทางเลือกเพื่อ json.dumps สำหรับฉันปัญหาเดียวกับของ json.dumps ใช้ นอกจากนี้คุณสามารถใช้ regex ง่าย ๆ ในการเปลี่ยนประเภทการเยื้องทำให้โค้ดของคุณง่ายขึ้น
y.petremann

0

นี่คือสิ่งที่จะพิมพ์พจนานุกรมที่ซ้อนกันทุกประเภทในขณะที่ติดตามพจนานุกรม "หลัก" ตลอดทาง

dicList = list()

def prettierPrint(dic, dicList):
count = 0
for key, value in dic.iteritems():
    count+=1
    if str(value) == 'OrderedDict()':
        value = None
    if not isinstance(value, dict):
        print str(key) + ": " + str(value)
        print str(key) + ' was found in the following path:',
        print dicList
        print '\n'
    elif isinstance(value, dict):
        dicList.append(key)
        prettierPrint(value, dicList)
    if dicList:
         if count == len(dic):
             dicList.pop()
             count = 0

prettierPrint(dicExample, dicList)

มันคือ จุดเริ่มต้นที่ดีสำหรับการพิมพ์ตามรูปแบบที่แตกต่างกันเช่นที่ระบุใน OP สิ่งที่คุณต้องทำคือการดำเนินการรอบ ๆบล็อกพิมพ์ โปรดทราบว่าดูเหมือนว่าจะมีค่าเป็น 'OrderedDict ()' ทั้งนี้ขึ้นอยู่กับว่าคุณกำลังใช้บางอย่างจากชุดข้อมูลคอนเทนเนอร์คุณควรสร้างตู้นิรภัยที่ล้มเหลวเหล่านี้เพื่อให้บล็อกelifไม่เห็นว่าเป็นพจนานุกรมเพิ่มเติมเนื่องจากชื่อของมัน ณ ตอนนี้พจนานุกรมตัวอย่างเช่น

example_dict = {'key1': 'value1',
            'key2': 'value2',
            'key3': {'key3a': 'value3a'},
            'key4': {'key4a': {'key4aa': 'value4aa',
                               'key4ab': 'value4ab',
                               'key4ac': 'value4ac'},
                     'key4b': 'value4b'}

จะพิมพ์

key3a: value3a
key3a was found in the following path: ['key3']

key2: value2
key2 was found in the following path: []

key1: value1
key1 was found in the following path: []

key4ab: value4ab
key4ab was found in the following path: ['key4', 'key4a']

key4ac: value4ac
key4ac was found in the following path: ['key4', 'key4a']

key4aa: value4aa
key4aa was found in the following path: ['key4', 'key4a']

key4b: value4b
key4b was found in the following path: ['key4']

~ การแก้ไขโค้ดให้เหมาะกับรูปแบบของคำถาม ~

lastDict = list()
dicList = list()
def prettierPrint(dic, dicList):
    global lastDict
    count = 0
    for key, value in dic.iteritems():
        count+=1
        if str(value) == 'OrderedDict()':
            value = None
        if not isinstance(value, dict):
            if lastDict == dicList:
                sameParents = True
            else:
                sameParents = False

            if dicList and sameParents is not True:
                spacing = ' ' * len(str(dicList))
                print dicList
                print spacing,
                print str(value)

            if dicList and sameParents is True:
                print spacing,
                print str(value)
            lastDict = list(dicList)

        elif isinstance(value, dict):
            dicList.append(key)
            prettierPrint(value, dicList)

        if dicList:
             if count == len(dic):
                 dicList.pop()
                 count = 0

ใช้รหัสตัวอย่างเดียวกันมันจะพิมพ์ต่อไปนี้:

['key3']
         value3a
['key4', 'key4a']
                  value4ab
                  value4ac
                  value4aa
['key4']
         value4b

นี้ไม่ได้ว่าสิ่งที่ร้องขอใน OP ข้อแตกต่างคือพาเรนต์ ^ n ยังคงถูกพิมพ์แทนที่จะขาดหายไปและแทนที่ด้วยช่องว่างสีขาว ในการไปที่รูปแบบของ OP คุณจะต้องทำสิ่งต่อไปนี้: เปรียบเทียบdicListซ้ำกับlastDictอย่างซ้ำๆ คุณสามารถทำได้โดยการสร้างพจนานุกรมใหม่และคัดลอกเนื้อหาของ dicList ลงไปตรวจสอบว่าiในพจนานุกรมที่คัดลอกนั้นเหมือนกับiใน lastDict หรือไม่และถ้าเป็น - กำลังเขียนช่องว่างไปยังiนั้นตำแหน่งโดยใช้ฟังก์ชั่นสตริงคูณ .


0

จากลิงค์นี้ :

def prnDict(aDict, br='\n', html=0,
            keyAlign='l',   sortKey=0,
            keyPrefix='',   keySuffix='',
            valuePrefix='', valueSuffix='',
            leftMargin=0,   indent=1 ):
    '''
return a string representive of aDict in the following format:
    {
     key1: value1,
     key2: value2,
     ...
     }

Spaces will be added to the keys to make them have same width.

sortKey: set to 1 if want keys sorted;
keyAlign: either 'l' or 'r', for left, right align, respectively.
keyPrefix, keySuffix, valuePrefix, valueSuffix: The prefix and
   suffix to wrap the keys or values. Good for formatting them
   for html document(for example, keyPrefix='<b>', keySuffix='</b>'). 
   Note: The keys will be padded with spaces to have them
         equally-wide. The pre- and suffix will be added OUTSIDE
         the entire width.
html: if set to 1, all spaces will be replaced with '&nbsp;', and
      the entire output will be wrapped with '<code>' and '</code>'.
br: determine the carriage return. If html, it is suggested to set
    br to '<br>'. If you want the html source code eazy to read,
    set br to '<br>\n'

version: 04b52
author : Runsun Pan
require: odict() # an ordered dict, if you want the keys sorted.
         Dave Benjamin 
         http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/161403
    '''

    if aDict:

        #------------------------------ sort key
        if sortKey:
            dic = aDict.copy()
            keys = dic.keys()
            keys.sort()
            aDict = odict()
            for k in keys:
                aDict[k] = dic[k]

        #------------------- wrap keys with ' ' (quotes) if str
        tmp = ['{']
        ks = [type(x)==str and "'%s'"%x or x for x in aDict.keys()]

        #------------------- wrap values with ' ' (quotes) if str
        vs = [type(x)==str and "'%s'"%x or x for x in aDict.values()] 

        maxKeyLen = max([len(str(x)) for x in ks])

        for i in range(len(ks)):

            #-------------------------- Adjust key width
            k = {1            : str(ks[i]).ljust(maxKeyLen),
                 keyAlign=='r': str(ks[i]).rjust(maxKeyLen) }[1]

            v = vs[i]        
            tmp.append(' '* indent+ '%s%s%s:%s%s%s,' %(
                        keyPrefix, k, keySuffix,
                        valuePrefix,v,valueSuffix))

        tmp[-1] = tmp[-1][:-1] # remove the ',' in the last item
        tmp.append('}')

        if leftMargin:
          tmp = [ ' '*leftMargin + x for x in tmp ]

        if html:
            return '<code>%s</code>' %br.join(tmp).replace(' ','&nbsp;')
        else:
            return br.join(tmp)     
    else:
        return '{}'

'''
Example:

>>> a={'C': 2, 'B': 1, 'E': 4, (3, 5): 0}

>>> print prnDict(a)
{
 'C'   :2,
 'B'   :1,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, sortKey=1)
{
 'B'   :1,
 'C'   :2,
 'E'   :4,
 (3, 5):0
}

>>> print prnDict(a, keyPrefix="<b>", keySuffix="</b>")
{
 <b>'C'   </b>:2,
 <b>'B'   </b>:1,
 <b>'E'   </b>:4,
 <b>(3, 5)</b>:0
}

>>> print prnDict(a, html=1)
<code>{
&nbsp;'C'&nbsp;&nbsp;&nbsp;:2,
&nbsp;'B'&nbsp;&nbsp;&nbsp;:1,
&nbsp;'E'&nbsp;&nbsp;&nbsp;:4,
&nbsp;(3,&nbsp;5):0
}</code>

>>> b={'car': [6, 6, 12], 'about': [15, 9, 6], 'bookKeeper': [9, 9, 15]}

>>> print prnDict(b, sortKey=1)
{
 'about'     :[15, 9, 6],
 'bookKeeper':[9, 9, 15],
 'car'       :[6, 6, 12]
}

>>> print prnDict(b, keyAlign="r")
{
        'car':[6, 6, 12],
      'about':[15, 9, 6],
 'bookKeeper':[9, 9, 15]
}
'''

0

ฉันเพิ่งกลับมาที่คำถามนี้หลังจากตอบคำถามของsthแล้วทำการดัดแปลงเล็กน้อย แต่มีประโยชน์มาก ฟังก์ชันนี้พิมพ์คีย์ทั้งหมดในแผนผัง JSONเช่นเดียวกับขนาดของโหนดปมในแผนผังนั้น

def print_JSON_tree(d, indent=0):
    for key, value in d.iteritems():
        print '    ' * indent + unicode(key),
        if isinstance(value, dict):
            print; print_JSON_tree(value, indent+1)
        else:
            print ":", str(type(d[key])).split("'")[1], "-", str(len(unicode(d[key])))

เป็นเรื่องที่ดีมากเมื่อคุณมีวัตถุ JSON ขนาดใหญ่และต้องการทราบว่าเนื้ออยู่ที่ไหน ตัวอย่าง :

>>> print_JSON_tree(JSON_object)
key1
    value1 : int - 5
    value2 : str - 16
    key2
       value1 : str - 34
       value2 : list - 5623456

นี่จะบอกคุณว่าข้อมูลส่วนใหญ่ที่คุณสนใจนั้นน่าจะอยู่ข้างในJSON_object['key1']['key2']['value2']เพราะความยาวของค่าที่จัดรูปแบบเป็นสตริงมีขนาดใหญ่มาก


0

ใช้ฟังก์ชั่นนี้:

def pretty_dict(d, n=1):
    for k in d:
        print(" "*n + k)
        try:
            pretty_dict(d[k], n=n+4)
        except TypeError:
            continue

เรียกว่าเป็นแบบนี้:

pretty_dict(mydict)

สิ่งนี้จะไม่ทำงานหากค่านั้นเป็นสตริง มันพิมพ์อักขระแต่ละตัวของสตริงบนบรรทัดใหม่ แต่แป้นดูเหมือนจะทำงานได้ดี
แอนโธนี

0

นี่คือสิ่งที่ฉันคิดขึ้นมาในขณะที่ทำงานกับชั้นเรียนที่จำเป็นต้องเขียนพจนานุกรมในไฟล์. txt:

@staticmethod
def _pretty_write_dict(dictionary):

    def _nested(obj, level=1):
        indentation_values = "\t" * level
        indentation_braces = "\t" * (level - 1)
        if isinstance(obj, dict):
            return "{\n%(body)s%(indent_braces)s}" % {
                "body": "".join("%(indent_values)s\'%(key)s\': %(value)s,\n" % {
                    "key": str(key),
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                } for key, value in obj.items()),
                "indent_braces": indentation_braces
            }
        if isinstance(obj, list):
            return "[\n%(body)s\n%(indent_braces)s]" % {
                "body": "".join("%(indent_values)s%(value)s,\n" % {
                    "value": _nested(value, level + 1),
                    "indent_values": indentation_values
                } for value in obj),
                "indent_braces": indentation_braces
            }
        else:
            return "\'%(value)s\'" % {"value": str(obj)}

    dict_text = _nested(dictionary)
    return dict_text

ตอนนี้ถ้าเรามีพจนานุกรมเช่นนี้:

some_dict = {'default': {'ENGINE': [1, 2, 3, {'some_key': {'some_other_key': 'some_value'}}], 'NAME': 'some_db_name', 'PORT': '', 'HOST': 'localhost', 'USER': 'some_user_name', 'PASSWORD': 'some_password', 'OPTIONS': {'init_command': 'SET foreign_key_checks = 0;'}}}

และเราทำ:

print(_pretty_write_dict(some_dict))

เราได้รับ:

{
    'default': {
        'ENGINE': [
            '1',
            '2',
            '3',
            {
                'some_key': {
                    'some_other_key': 'some_value',
                },
            },
        ],
        'NAME': 'some_db_name',
        'OPTIONS': {
            'init_command': 'SET foreign_key_checks = 0;',
        },
        'HOST': 'localhost',
        'USER': 'some_user_name',
        'PASSWORD': 'some_password',
        'PORT': '',
    },
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.