【问题标题】:parse multilevel json to string with condition将多级 json 解析为带条件的字符串
【发布时间】:2017-04-14 17:04:50
【问题描述】:

我有这个嵌套的 json 项目,我只想将它展平为一个逗号分隔的字符串(即 parkinson:5,billy mays:4),以便在需要时将其存储在数据库中以供将来分析。我写了下面的函数,但想知道是否有使用列表理解(或其他东西)的更优雅的方式。我找到了这篇文章,但我不确定如何根据我的需要调整它 (Python - parse JSON values by multilevel keys)。

数据如下所示:

{'persons':
     [{'name': 'parkinson', 'sentiment': '5'},
      {'name': 'knott david', 'sentiment': 'none'},
      {'name': 'billy mays', 'sentiment': '4'}],
 'organizations':
      [{'name': 'piper jaffray companies', 'sentiment': 'none'},
       {'name': 'marketbeat.com', 'sentiment': 'none'},
       {'name': 'zacks investment research', 'sentiment': 'none'}]
 'locations': []
}

这是我的代码:

def parse_entities(data):
    results = ''
    for category in data.keys():
    # for c_id, category in enumerate(data.keys()):
        entity_data = data[category]
        for e_id, entity in enumerate(entity_data):
            if not entity_data[e_id]['sentiment'] == 'none':
                results = results + (data[category][e_id]['name'] + ":" +
                                     data[category][e_id]['sentiment'] + ",")

    return results

【问题讨论】:

  • 为什么不使用csv library
  • 我可以用它来解析数据并将其组合成一个长字符串吗?我不想将它保存为文件,我只想要一个逗号分隔的字符串。我已经更新了我的问题。

标签: python json


【解决方案1】:

首先,让您的代码更短、更美观最重要的是使用您自己的变量。请注意entity_data = data[category]entity = entity_data[e_id]。所以你可以写entity['name']而不是data[category][e_id]['name']

其次,如果你想要类似的东西

for category in data.keys():
    entity_data = data[category]

你可以把它改成更短更容易阅读

for category, entity_data in data.items():

但是你甚至不需要在这里,你可以使用 data.values() 迭代器来获取值。结合这些改进时,您的代码如下所示:

def parse_entities(data):
    results = ''
    for entity_data in data.values():
        for entity in entity_data:
            if entity['sentiment'] != 'none':
                results += entity['name'] + ":" + entity['sentiment'] + ","
    return results

(我也将results = results + ...改为results += ...if not entity['sentiment'] == 'none'改为if entity['sentiment'] != 'none',因为它更短且不会降低可读性)

当你有这个时,使用列表推导更容易使它更短更优雅:

def parse_entities(data):
    return ",".join([entity['name'] + ":" + entity['sentiment']
                     for entity_data in data.values()
                     for entity in entity_data
                     if not entity['sentiment'] == 'none'])

【讨论】:

  • 这就是我要找的。我选择这个作为接受的答案,因为它创建了我正在寻找使用列表理解的简短函数,我解释了你是如何转换我的以及原因。
【解决方案2】:

也许这样的事情会起作用?

def parse_entities(data):
    results = []
    for category in data.keys():
        results += list(map(lambda x: '{0}:{1}'.format(x['name'], x['sentiment']),
                            filter(lambda i: i['sentiment'] != 'none', data[category])))
    return ','.join(results)

if __name__ == '__main__':
    print(parse_entities(data))

输出看起来像这样

parkinson:5,billy mays:4

【讨论】:

  • 'none' 应该被过滤掉。
【解决方案3】:

这可能是一种方法。即使使用“适当的库”(取决于您的实际用例)更有意义。

data = {
 'persons':
     [{'name': 'parkinson', 'sentiment': '5'},
      {'name': 'knott david', 'sentiment': 'none'},
      {'name': 'billy mays', 'sentiment': '4'}],
 'organizations':
      [{'name': 'piper jaffray companies', 'sentiment': 'none'},
       {'name': 'marketbeat.com', 'sentiment': 'none'},
       {'name': 'zacks investment research', 'sentiment': 'none'}],
 'locations': []
}

import itertools

# eq. = itertools.chain.from_iterable(data.values())
dicts = itertools.chain(*data.values())
pairs = [":".join([d['name'], d['sentiment']])
         for d in dicts if d['sentiment'] != 'none']
result = ",".join(pairs)

print(result)

# parkinson:5,billy mays:4

# short, but less readable version
result = ",".join([":".join([d['name'], d['sentiment']])
                   for d in itertools.chain(*data.values())
                   if d['sentiment'] != 'none'])

【讨论】:

    【解决方案4】:

    这是一个问题,我们需要执行 3 个单独的任务:

    1. 过滤掉不合格的数据行
    2. 将列表的 dict 扁平化为一个简单的列表
    3. 将每个字典对象转换为一个简单的元组,准备好格式化

    代码如下:

    def parse_entities(data):
        new_data = [
            (row['name'], row['sentiment'])        # 3. Transform
            for rows in data.values()              # 2. Flatten
                for row in rows                    # 2. Flatten
                    if row['sentiment'] != 'none'  # 1. Filter
        ]
    
        # e.g, new_data = [('parkinson', '5'), ('billy mays', '4')]
    
        return ','.join('{}:{}'.format(*row) for row in new_data)
    
    #
    # test code
    #
    data = {
        'locations': [],
        'organizations': [
            {'name': 'piper jaffray companies', 'sentiment': 'none'},
            {'name': 'marketbeat.com', 'sentiment': 'none'},
            {'name': 'zacks investment research', 'sentiment': 'none'}
        ],
        'persons': [
            {'name': 'parkinson', 'sentiment': '5'},
            {'name': 'knott david', 'sentiment': 'none'},
            {'name': 'billy mays', 'sentiment': '4'}
        ],
    }
    print parse_entities(data)
    

    输出:

    parkinson:5,billy mays:4
    

    【讨论】:

      【解决方案5】:

      这是一个generator expression

      data = {'persons': [
                  {'name': 'parkinson', 'sentiment': '5'},
                  {'name': 'knott david', 'sentiment': 'none'},
                  {'name': 'billy mays', 'sentiment': '4'}],
              'organizations': [
                  {'name': 'piper jaffray companies', 'sentiment': 'none'},
                  {'name': 'marketbeat.com', 'sentiment': '99'},
                  {'name': 'zacks investment research', 'sentiment': 'none'}],
              'locations': []
      }
      
      results = ','.join(entity['name'] + ':' + entity['sentiment']
                          for category, entity_data in data.items()
                              for entity in entity_data if entity['sentiment'] is not 'none')
      
      
      print(results)  # -> parkinson:5,billy mays:4,marketbeat.com:99
      

      注意:我稍微更改了示例数据,以确保它处理多个category 中的数据与您的代码相同。

      【讨论】:

        猜你喜欢
        • 2019-12-20
        • 1970-01-01
        • 2011-03-14
        • 1970-01-01
        • 1970-01-01
        • 2012-10-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多