【问题标题】:Hierarchical grouping in key value pair with python使用python在键值对中进行分层分组
【发布时间】:2017-09-25 23:38:33
【问题描述】:

我有一个这样的列表:

data = [
{'date':'2017-01-02', 'model': 'iphone5', 'feature':'feature1'},
{'date':'2017-01-02', 'model': 'iphone7', 'feature':'feature2'},
{'date':'2017-01-03', 'model': 'iphone6', 'feature':'feature2'},
{'date':'2017-01-03', 'model': 'iphone6', 'feature':'feature2'},
{'date':'2017-01-03', 'model': 'iphone7', 'feature':'feature3'},
{'date':'2017-01-10', 'model': 'iphone7', 'feature':'feature2'},
{'date':'2017-01-10', 'model': 'iphone7', 'feature':'feature1'},
]

我想实现这个:

[
   {
      '2017-01-02':[{'iphone5':['feature1']}, {'iphone7':['feature2']}]
   },
   {
      '2017-01-03': [{'iphone6':['feature2']}, {'iphone7':['feature3']}]
   },
   {
      '2017-01-10':[{'iphone7':['feature2', 'feature1']}]
   }
]

我需要一种有效的方法,因为它可能包含大量数据。

我正在尝试这个:

data = sorted(data, key=itemgetter('date'))
date = itertools.groupby(data, key=itemgetter('date'))

但对于“日期”键的值,我一无所获。

稍后我将遍历此结构以构建 HTML。

【问题讨论】:

标签: python python-2.7 grouping


【解决方案1】:

您可以使用defaultdict 高效而干净地完成此操作。不幸的是,这是一个相当高级的用法,而且很难阅读。

from collections import defaultdict
from pprint import pprint

# create a dictionary whose elements are automatically dictionaries of sets
result_dict = defaultdict(lambda: defaultdict(set))

# Construct a dictionary with one key for each date and another dict ('model_dict') 
# as the value.
# The model_dict has one key for each model and a set of features as the value.
for d in data:
    result_dict[d["date"]][d["model"]].add(d["feature"])

# more explicit version:
# for d in data:
#     model_dict = result_dict[d["date"]]   # created automatically if needed
#     feature_set = model_dict[d["model"]]  # created automatically if needed
#     feature_set.add(d["feature"])

# convert the result_dict into the required form
result_list = [
    {   
        date: [
            {phone: list(feature_set)} 
                for phone, feature_set in sorted(model_dict.items())
        ]
    } for date, model_dict in sorted(result_dict.items())
]

pprint(result_list)
# [{'2017-01-02': [{'iphone5': ['feature1']}, {'iphone7': ['feature2']}]},
#  {'2017-01-03': [{'iphone6': ['feature2']}, {'iphone7': ['feature3']}]},
#  {'2017-01-10': [{'iphone7': ['feature2', 'feature1']}]}]

【讨论】:

    【解决方案2】:

    你可以试试这个,这是我的方法,td 是一个存储{ iphone : index } 的字典,用于检查字典列表中是否存在新项目:

    from itertools import groupby
    from operator import itemgetter
    
    r = []
    for i in groupby(sorted(data, key=itemgetter('date')), key=itemgetter('date')):
        td, tl = {}, []
        for j in i[1]:
            if j["model"] not in td:
                tl.append({j["model"]: [j["feature"]]})
                td[j["model"]] = len(tl) - 1
            elif j["feature"] not in tl[td[j["model"]]][j["model"]]:
                tl[td[j["model"]]][j["model"]].append(j["feature"])
        r.append({i[0]: tl})
    

    结果:

    [
      {'2017-01-02': [{'iphone5': ['feature1']}, {'iphone7': ['feature2']}]},
      {'2017-01-03': [{'iphone6': ['feature2']}, {'iphone7': ['feature3']}]},
      {'2017-01-10': [{'iphone7': ['feature2', 'feature1']}]}
    ]
    

    其实我觉得数据结构可以简化,也许你不需要那么多嵌套。

    【讨论】:

      【解决方案3】:
      total_result = list()
      result = dict()
      inner_value = dict()
      
      for d in data:
          if d["date"] not in result:
              if result:
                  total_result.append(result)
              result = dict()
              result[d["date"]] = set()
              inner_value = dict()
      
          if d["model"] not in inner_value:
              inner_value[d["model"]] = set()
      
          inner_value[d["model"]].add(d["feature"])
          tmp_v = [{key: list(inner_value[key])} for key in inner_value]
          result[d["date"]] = tmp_v
      
      total_result.append(result)
      

      total_result

      [{'2017-01-02': [{'iphone7': ['feature2']}, {'iphone5': ['feature1']}]},
       {'2017-01-03': [{'iphone6': ['feature2']}, {'iphone7': ['feature3']}]},
       {'2017-01-10': [{'iphone7': ['feature2', 'feature1']}]}]
      

      【讨论】:

      • 我认为这可能只有在数据事先按日期排序的情况下才有效。
      猜你喜欢
      • 2022-12-03
      • 2013-08-13
      • 2019-03-20
      • 2015-06-05
      • 2021-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多