简体   繁体   English

使用setdefault重构Python字典列表

[英]Re-structuring a list of Python Dicts using setdefault

I am trying to re-structure a list of Python dictionaries by 'grouping' (that's probably not the correct expression, but using it as a proxy based on SQL) the dictionaries based on a (non-unique) value. 我试图通过“分组”(可能不是正确的表达式,但是将其用作基于SQL的代理)基于(非唯一)值的字典来重新构建Python字典列表。 I have got close, however I'm falling at the final hurdle, in that I couldn't work out how to re-assign each value to a name (ie I end up with what looks like a tuple rather than a dict). 我已经接近了,但是我遇到了最后的障碍,因为我无法解决如何将每个值重新分配给一个名称(即,我得到的看起来像是元组而不是字典)。

Additionally I have a superfluous list (ie my output ends up as [[{...}]] rather than [{...}]. 另外,我还有一个多余的列表(即,我的输出最终以[[{...}]]而不是[{...}]结束。

I have used the example here: 我在这里使用了示例:

How do I group this list of dicts by the same month? 如何在同一个月将字典列表分组?

Which gets me quite close to what I want, however I'm stuck at the final stage! 这使我非常接近我想要的东西,但是我被困在最后阶段!

market = [
    {'selection_id': 1099, 'value': '11', 'value_name': 'a'},
    {'selection_id': 1099, 'value': '78', 'value_name': 'p'},
    {'selection_id': 1097, 'value': '39', 'value_name': 'b'},
    {'selection_id': 1097, 'value': '52', 'value_name': 'f'},
    {'selection_id': 1098, 'value': '98', 'value_name': 'd'},
    {'selection_id': 1099, 'value': '13', 'value_name': 'y'},
    {'selection_id': 1098, 'value': '4', 'value_name': 'r'},
]

new_structure = {}
new_structure2 = []

for z in market:
        new_structure.setdefault(z['selection_id'], []).append((z['value'], z['value_name']))
        t = [{'selection_id': m, 'value_dict': n} for m, n in new_structure.items()]
new_structure2.append(t)

print(new_structure2)

This outputs as: 输出为:

[[{'selection_id': 1099, 'value_dict': [('11', 'a'), ('78', 'p'), ('13',  
 'y')]}, {'selection_id': 1097, 'value_dict': [('39', 'b'), ('52', 'f')]},  
 {'selection_id': 1098, 'value_dict': [('98', 'd'), ('4', 'r')]}]]

Which is very close, however what I'm aiming for is: 这非常接近,但是我的目标是:

[{'selection_id': 1099,
  'value_dict': [{'value': '11', 'value_name': 'a'},
                 {'value': '78', 'value_name': 'p'},
                 {'value': '13', 'value_name': 'y'}]},
 {'selection_id': 1097,
  'value_dict': [{'value': '39', 'value_name': 'b'},
                 {'value': '52', 'value_name': 'f'}]},
 {'selection_id': 1098,
  'value_dict': [{'value': '98', 'value_name': 'd'},
                 {'value': '4', 'value_name': 'r'}]}]

I appreciate its probably a really simple fix, but its escaping me at the moment, so any guidance would be greatly appreciated! 我很感激它可能是一个非常简单的修复程序,但此刻它使我逃脱了,因此任何指导将不胜感激!

Here are some hints: 这里有一些提示:

The first thing is to sort by selection_id : 第一件事是按selection_id排序:

by_selection_id = operator.itemgetter('selection_id')
market.sort(key=by_selection_id)

Then you can group by selection_id : 然后,您可以按selection_id进行分组:

for selection_id, group in itertools.groupby(market, key=by_selection_id):
    print(selection_id, list(group))

You get: 你得到:

(1097, [{'value_name': 'b', 'value': '39', 'selection_id': 1097},
        {'value_name': 'f', 'value': '52', 'selection_id': 1097}])
(1098, [{'value_name': 'd', 'value': '98', 'selection_id': 1098},
        {'value_name': 'r', 'value': '4', 'selection_id': 1098}])
(1099, [{'value_name': 'a', 'value': '11', 'selection_id': 1099},
        {'value_name': 'p', 'value': '78', 'selection_id': 1099},
        {'value_name': 'y', 'value': '13', 'selection_id': 1099}])

Then it is easy to build the final list. 这样就很容易构建最终列表。

Here is a solution using comprehension list/dict: 这是使用理解列表/字典的解决方案:

new_structure = [{'selection_id': selection_id,
                  'value_dict': [{'value': item['value'],
                                  'value_name': item['value_name']} for item in group]}
                 for selection_id, group in itertools.groupby(market, key=by_selection_id)]

Or using a classic list with append : 或者使用带有append的经典列表:

new_structure = []
for selection_id, group in itertools.groupby(market, key=by_selection_id):
    value_dict = [{'value': item['value'], 'value_name': item['value_name']} for item in group]
    new_structure.append({'selection_id': selection_id,
                          'value_dict': value_dict})

I end up with what looks like a tuple rather than a dict) 我最终看起来像元组而不是字典)

This is because you are appending a tuple, not a dict: 这是因为您要追加一个元组,而不是一个dict:

.append((z['value'], z['value_name']))

So, just to update, based on the answer from @Code-Apprentice, I have re-written my code as follows: 因此,为了更新,基于@ Code-Apprentice的答案,我重新编写了代码,如下所示:

market = [
    {'selection_id': 1099, 'value': '11', 'value_name': 'a'},
    {'selection_id': 1099, 'value': '78', 'value_name': 'p'},
    {'selection_id': 1097, 'value': '39', 'value_name': 'b'},
    {'selection_id': 1097, 'value': '52', 'value_name': 'f'},
    {'selection_id': 1098, 'value': '98', 'value_name': 'd'},
    {'selection_id': 1099, 'value': '13', 'value_name': 'y'},
    {'selection_id': 1098, 'value': '4', 'value_name': 'r'},
]

new_structure = {}
new_structure2 = []

for z in market:
    new_structure.setdefault(z['selection_id'], []).append({'value': z['value'],
                                                            'value_name': z['value_name']})
    t = [{'selection_id': m, 'value_dict': n} for m, n in new_structure.items()]
    new_structure2.append(t)

print(new_structure2)

Which then gets me very close to my desired output. 然后,这使我非常接近所需的输出。 The only remaining issue I have, is a superfluous list (ie [[{....}]] instead of [{...}]), I believe this is probably because of the way I have written the line t=.... 我唯一剩下的问题是一个多余的列表(即[[[{....}]]而不是[{...}]),我相信这可能是因为我写了t = ....

Here is my output, I will post an update, once I've got rid of that extra list in case the answer is of use to anyone else (but please feel free to shout if you spot it before me): 这是我的输出,一旦摆脱了多余的清单,我将发布更新,以防答案对其他人有用(但是,如果在我之前发现它,请随时大喊大叫):

[[{'selection_id': 1099,
   'value_dict': [{'value': '11', 'value_name': 'a'},
                  {'value': '78', 'value_name': 'p'},
                  {'value': '13', 'value_name': 'y'}]},
  {'selection_id': 1097,
   'value_dict': [{'value': '39', 'value_name': 'b'},
                  {'value': '52', 'value_name': 'f'}]},
  {'selection_id': 1098,
   'value_dict': [{'value': '98', 'value_name': 'd'},
                  {'value': '4', 'value_name': 'r'}]}]]

So ridiculously basic! 太荒谬了! I was over-complicating it, just simply removed the extra list reference: 我太复杂了,只是简单地删除了额外的列表引用:

market = [
    {'selection_id': 1099, 'value': '11', 'value_name': 'a'},
    {'selection_id': 1099, 'value': '78', 'value_name': 'p'},
    {'selection_id': 1097, 'value': '39', 'value_name': 'b'},
    {'selection_id': 1097, 'value': '52', 'value_name': 'f'},
    {'selection_id': 1098, 'value': '98', 'value_name': 'd'},
    {'selection_id': 1099, 'value': '13', 'value_name': 'y'},
    {'selection_id': 1098, 'value': '4', 'value_name': 'r'},
]

new_structure = {}

for z in market:
    new_structure.setdefault(z['selection_id'], []).append({'value': z['value'],
                                                            'value_name': z['value_name']})

new_structure2 = [{'selection_id': m, 'value_dict': n} for m, n in new_structure.items()]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM