V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
oddcc
V2EX  ›  Python

Python | 包含元组的列表转 JSON,更好的做法?

  •  
  •   oddcc · 2016-11-29 15:16:50 +08:00 · 2413 次点击
    这是一个创建于 2918 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原始数据是一个由元组构成的列表,每个元组包含年、月、 P 级、数量,要转换成 JSON ,具体示例如下:

    # 原始数据
    rs=[(2016,1,'p0',1),(2016,2,'p1',2),(2016,2,'p2',3),(2016,3,'p3',25),(2016,4,'p4',55)]
    
    # 目标 JSON ,如果某月没有相应的 P 级的数据,要补 0
    {'p2': [0, 3, 0, 0], 
     'p3': [0, 0, 25, 0], 
     'p0': [1, 0, 0, 0], 
     'p1': [0, 2, 0, 0], 
     'p4': [0, 0, 0, 55], 
     'categories': ['2016-1', '2016-2', '2016-3', '2016-4']}
    

    下面是我的做法,是把数据先转换为 dict ,然后在遍历生成 JSON 的时候通过 setdefault 把缺失的数据补 0 。但是感觉很笨,不知道更好的做法是什么?

    # coding=utf-8
    rs=[(2016,1,'p0',1),(2016,2,'p1',2),(2016,2,'p2',3),(2016,3,'p3',25),(2016,4,'p4',55)]
    
    # 预处理,把 rs 转换为字典
    dict1 = {}
    
    for (year, month, p_level, count) in rs:
        dict1.setdefault(year,{})
        dict1[year].setdefault(month,{})
        dict1[year][month].setdefault(p_level,{})
        dict1[year][month][p_level] = count
    # dict1 >> {2016: {1: {'p0': 1}, 2: {'p2': 3, 'p1': 2}}}
    
    # 预处理,取年份月份和 P 级的集合,这样数据有变化也可以处理
    p_levels = []
    months = []
    years = []
    
    for i in rs:
        if i[0] not in years:
            years.append(i[0])
    
        if i[1] not in months:
            months.append(i[1])
    
        if i[2] not in p_levels:
            p_levels.append(i[2])
    months.sort()
    years.sort()
    
    result={}
    result['categories']=[str(year)+'-'+str(month) for year in years for month in months]
    
    for p_level in p_levels:
        for month in months:
            result.setdefault(p_level,[]).append(dict1[2016][month].get(p_level, 0))
    
    print result
    # {'p2': [0, 3, 0, 0], 
    # 'p3': [0, 0, 25, 0], 
    # 'p0': [1, 0, 0, 0], 
    # 'p1': [0, 2, 0, 0], 
    # 'p4': [0, 0, 0, 55], 
    # 'categories': ['2016-1', '2016-2', '2016-3', '2016-4']}
    
    2 条回复    2016-11-29 18:38:27 +08:00
    Bryan8
        1
    Bryan8  
       2016-11-29 17:48:44 +08:00   ❤️ 1
    ```Python
    rs = [(2016, 1, 'p0', 1), (2016, 2, 'p1', 2), (2016, 2, 'p2', 3),
    (2016, 3, 'p3', 25), (2016, 4, 'p4', 55)]

    dic = {'categories': []}

    month = max([i[1] for i in rs])


    for i in rs:
    dic.setdefault(i[2], [0 for j in range(month)])
    dic[i[2]][i[1] - 1] = i[3]
    dic['categories'].append(str(i[0]) + '-' + str(i[1]))

    print(dic)
    ```

    这样?
    oddcc
        2
    oddcc  
    OP
       2016-11-29 18:38:27 +08:00
    @Bryan8 谢谢回复,确实应该把预处理做的彻底一点,先全部初始化成 0 再填数据就好了…
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3085 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 14:07 · PVG 22:07 · LAX 06:07 · JFK 09:07
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.