Groupby by Python中的字典键

时间:2017-12-04 20:58:52

标签: python dictionary

我是Python的新手,如果有人回答

,我将不胜感激

我有以下字典列表

{'body': 'text'},
{'correctAnswer': 'text'},
{'ans': 'text'},
{'ans': 'text'}

所需的输出是:

{'body': 'text', 'correctAnswer': 'text','ans_1': 'text', 'ans_2': 'text'}

如何用所需的顺序替换键和值

4 个答案:

答案 0 :(得分:-1)

L = [{'body': 'text'},
{'correctAnswer': 'text'},
{'ans': 'text'},
{'ans': 'text'},
{'ans': 'text'}]

def key_startswith(new_key, new_value, old_d):
    keys_lst = list(old_d.keys())

    # check if there's a key that startswith the new_key
    if any(key.startswith(new_key) for key in keys_lst):

        # check if this key is exactly the same as the new key
        if any(key == new_key for key in keys_lst):
            old_d[new_key+"_1"] = old_d.pop(new_key)
            old_d[new_key+"_2"] = new_value

        # if not exactly the same, add key + "_" + num
        else:
            all_matches = [key for key in keys_lst if key.startswith(new_key)]
            splitted = [int(el.split("_")[-1]) for el in all_matches]
            new_number = max(splitted) + 1
            old_d[new_key+"_"+str(new_number)] = new_value

    else:
        old_d[new_key] = new_value

    return old_d


def zip_all_dicts(lst):
    output = {}

    for el in lst:

        if isinstance(el, dict):
            for k,v in el.items():
                output = key_startswith(k,v,output)

        # if not dict
        else:
            continue

    return output

zip_all_dicts(L)

也许不是最漂亮但易于理解且有效。

运行zip_all_dicts(L)会产生:

{'ans_1': 'text', 'ans_2': 'text', 'ans_3': 'text', 'body': 'text', 'correctAnswer': 'text'}

答案 1 :(得分:-1)

您可以使用更新方法实现此目的。

如果您有以下名为:

的词典
dict1 = {'body': 'text'}
dict2 = {'correctAnswer': 'text'}
dict3 = {'ans': 'text'}
dict4 = {'ans': 'text'}

然后通过以下操作将获得所需的:

d0 = dict1.copy()
d0.update(dict2)
d0.update(dict3)
d0.update(dict4)
print(d0)#will contain all 4 dicts

如果您有一个dicts数组并且需要迭代,您可以想象如何使用循环执行此操作。

编辑: 刚看到你想要不同的钥匙。您可以在每次更新之前执行以下操作以进行检查:

countDict = {}

key = 'ans'
if key in countDict:
    i = countDict[key]
    countDict[key] = i+1
    key+str(i)
else:
    countDict[key] = 0

d0[key] = 'text'

答案 2 :(得分:-1)

您可以使用itertools.groupby

from itertools import groupby

lst = [{'body': 'text'}, {'correctAnswer': 'text'}, {'ans': 'text'},
       {'ans': 'text'}]
lst.sort(key=lambda x: list(x)[0])

d = {}

for k, g in groupby(lst, key=lambda x: list(x)[0]):
    l = list(g)
    if len(l) > 1:
        for i, v in enumerate(l, 1):
            d["{}_{}".format(k, i)] = list(v.values())[0]
    else:
        d[k] = list(l[0].values())[0]
print(d)  # {'body': 'text', 'correctAnswer': 'text', 'ans_1': 'text', 'ans_2': 'text'}

答案 3 :(得分:-1)

你可以试试这个:

import itertools, re
s = [{'body': 'text'}, {'correctAnswer': 'text'}, {'ans': 'text'}, {'ans': 'text'}]
new_data = list(itertools.chain.from_iterable([i.items() for i in s]))
final_data = [(a, list(b)) for a, b in itertools.groupby(sorted(new_data), key=lambda x:x[0])]
possibilies = [(a, [i[-1] for i in b]) for a, b in final_data]
final_dict = {}
for key, value in possibilies:
   for i, a in enumerate(value, start = 1):
       final_dict["{}_{}".format(key, i)] = a 

new_final_dict = {a[:a.index('_')] if [c[:c.index('_')] for c in final_dict].count(a[:a.index('_')]) == 1 else a:b for a, b in final_dict.items()}
sort_key = ['body', 'correctAnswer', 'ans_1', 'ans_2']
final_data = sorted(new_final_dict.items(), key=lambda x:sort_key.index(x[0]) if not x[0][-1].isdigit() else int(re.findall('\d+$', x[0])[0]))
print(final_data)

输出:

[('body', 'text'), ('correctAnswer', 'text'), ('ans_1', 'text'), ('ans_2', 'text')]

使用collections.OrderedDict

from collections import OrderedDict
d = OrderedDict()
sort_key = ['body', 'correctAnswer', 'ans_1', 'ans_2']
final_data = sorted(new_final_dict.items(), key=lambda x:sort_key.index(x[0]) if not x[0][-1].isdigit() else int(re.findall('\d+$', x[0])[0]))
for a, b in final_data:
    d[a] = b

print(d)

输出:

OrderedDict([('body', 'text'), ('correctAnswer', 'text'), ('ans_1', 'text'), ('ans_2', 'text')])

OrderedDict将允许您按所需的排序顺序查看字典的包含,并且还允许您像通常的字典一样按键访问值。