【问题标题】:Merge and create a new JSON array of all the records with same id合并并创建具有相同 id 的所有记录的新 JSON 数组
【发布时间】:2018-10-12 11:01:09
【问题描述】:

我必须合并并创建一个包含字典列表中具有相同 cluster_id 的所有记录的 JSON 数组。例如: id: 1 & 2 具有相同的 cluster_id 字段,因此它们应合并,如预期输出所示,3 个字段 id、name、match_full_address 应显示为 JSON 数组,用于新字段记录,对于 id 为 3 的单例记录也应显示为 JSON 数组.

我的词典列表:

[{
    'id': 1,
    'name': 'Will Smith',
    'match_full_address': 'Ridge Boulevard,123 Main Street,Branchburg,NJ',
    'cluster_id': 91,
    'lat': 18756.73,
    'longi': -97.395351,
},
{
    'id': 2,
    'name': 'Sandra Bullock',
    'match_full_address': 'New Castle,123 Mountain Ave,Branchburg,NJ',
    'cluster_id': 91,
    'lat': 18756.73,
    'longi': -97.395351,
},
{
    'id': 3,
    'name': 'Tom Cruise',
    'match_full_address': 'MI2, 123 Syracuse Avenue, Branchburg,NJ',
    'cluster_id': 92,
    'lat': 18756.73,
    'longi': -97.395351,
}
]

预期输出

[{
    'cluster_id': 91,
    'lat': 18756.73,
    'longi': -97.395351,
        'records': [{'id': 1,
    'name': 'Will Smith',
    'match_full_address': 'Ridge Boulevard,123 Main Street,Branchburg,NJ'},
    {'id': 2,
    'name': 'Sandra Bullock',
    'match_full_address': 'New Castle,123 Mountain Ave,Branchburg,NJ'}]
},
{
    'cluster_id': 92,
    'lat': 18756.73,
    'longi': -97.395351,
 'records': [{  'id': 3,
    'name': 'Tom Cruise',
    'match_full_address': 'MI2, 123 Syracuse Avenue, Branchburg,NJ'}
}
]

【问题讨论】:

    标签: python json python-3.x


    【解决方案1】:

    您可以使用临时字典来跟踪同一 cluster_id 的记录,并继续将感兴趣的键附加到记录中。

    假设您的 dicts 列表存储在变量 l 中:

    t = {}
    for d in l:
        if d['cluster_id'] not in t:
            t[d['cluster_id']] = {k: d.get(k, []) for k in ('cluster_id', 'lat', 'longi', 'records')}
        t[d['cluster_id']]['records'].append({k: d[k] for k in ('id', 'name', 'match_full_address')})
    

    list(t.values()) 会返回:

    [{'cluster_id': 91,
      'lat': 18756.73,
      'longi': -97.395351,
      'records': [{'id': 1,
                   'match_full_address': 'Ridge Boulevard,123 Main '
                                         'Street,Branchburg,NJ',
                   'name': 'Will Smith'},
                  {'id': 2,
                   'match_full_address': 'New Castle,123 Mountain '
                                         'Ave,Branchburg,NJ',
                   'name': 'Sandra Bullock'}]},
     {'cluster_id': 92,
      'lat': 18756.73,
      'longi': -97.395351,
      'records': [{'id': 3,
                   'match_full_address': 'MI2, 123 Syracuse Avenue, Branchburg,NJ',
                   'name': 'Tom Cruise'}]}]
    

    【讨论】:

      【解决方案2】:

      这类问题很常见。答案永远是:sorted+groupby

      def cluster_id_key(record):
          return record['cluster_id']
      
      def process(data):
          sorted_data = sorted(data, key=cluster_id_key)
          for cluster_id, records in groupby(sorted_data, key=cluster_id_key):
              records = list(records)
              common_props = [k for k,v records[0].items() if all(v==r[k] for r in records)]
              cluster_data = {k: v for k,v in records[0].items() if k in common_props}
              reduced_records = [{k:v for k,v in record.items() if k not in common_props} for record in records]
              yield {**cluster_data 'records': reduced_records}
      

      上面的解决方案处理了像lat 这样的属性对于集群中的所有元素可能并不相同的情况。在这种情况下,它会自动在records 数组中插入lat,而不是在集群级别。此外,如果所有记录共有相同的值,则将其放在 records 之外。

      我会把它当作一个练习来调整它以获得你想要的输出。

      【讨论】:

        【解决方案3】:

        虽然您仍然可以使用推导式,但我认为这不是一个好的案例。因此,只需简单地重申您的列表即可。

        #!/usr/bin/env python3
        import json
        
        
        listM = [{
            'id': 1,
            'name': 'Will Smith',
            'match_full_address': 'Ridge Boulevard,123 Main Street,Branchburg,NJ',
            'cluster_id': 91,
            'lat': 18756.73,
            'longi': -97.395351,
        },
        {
            'id': 2,
            'name': 'Sandra Bullock',
            'match_full_address': 'New Castle,123 Mountain Ave,Branchburg,NJ',
            'cluster_id': 91,
            'lat': 18756.73,
            'longi': -97.395351,
        },
        {
            'id': 3,
            'name': 'Tom Cruise',
            'match_full_address': 'MI2, 123 Syracuse Avenue, Branchburg,NJ',
            'cluster_id': 92,
            'lat': 18756.73,
            'longi': -97.395351,
        }
        ]
        
        clusters = dict()
        for item in listM:
            data = clusters.get(item['cluster_id'], {})
            if len(data) == 0:
                data["cluster_id"] = item["cluster_id"]
                data["lat"] = item["lat"]
                data["long"] = item["longi"]
                data["records"] = []
        
            data["records"].append(
                dict({
                    'id': item['id'],
                    'name': item['name'],
                    'match_full_address': item['match_full_address']
                    })
                )
            clusters.update({ item['cluster_id']: data })
        
        print(list(clusters.values()))
        

        【讨论】:

          猜你喜欢
          • 2014-10-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-02
          • 1970-01-01
          • 2017-05-05
          • 2023-03-04
          相关资源
          最近更新 更多