J'ai deux listes de dictionnaires. Appelons le premier comme dd:
[{'11': {'xx': '259', 'priority': '1', 'channels': '55'}}, {'11': {'xx': '270', 'priority': '11', 'channels': '35'}}, {'11': {'xx': '260', 'priority': '2', 'channels': '35'}}, {'22': {'xx': '300', 'priority': '1', 'channels': '40'}}, {'33': {'xx': '400', 'priority': '1', 'channels': '40'}}]
Les fonctionnalités clés de l'élément dict sont id c'est-à-dire 11,22, 33 et la priorité ie 1,2,3..
Un autre dict est un filtre dict :
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '4', 'channels': '35'}},
{'11': {'xx': '260', 'priority': '9', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '11', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
Ce filtre dict a une valeur-clé où clé définit le id dans le premier dict dd et la valeur signifie le nombre d'éléments à sélectionner à partir du premier dict dd c.-à-d. {'11': 2} signifie sélectionner les 2 éléments supérieurs du dd en fonction de la priorité code>. Et sélectionnez un seul élément prioritaire dans jj si filter_dct ne contient pas l ' id correspondant.
Ce que j'ai jusqu'à présent, c'est un moyen d'obtenir seulement 1 élément prioritaire du dd basé sur priority:
res = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}}, # one elem because no record in the filter_dict
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}]
Résultat souhaité que j'essaie d'obtenir:
tmp = {}
for elem in dd:
tmp.setdefault([*elem][0], []).append(elem)
out = [subl[0] for subl in tmp.values()]
print(out)
MODIFIER:
Les solutions proposées échouent lorsque les éléments sont plus supérieur à 4.
ie pour l'entrée:
filter_dict = [{'11': 2}, {'33': 2}]
la sortie est:
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
Ce qui est incorrect.
4 Réponses :
Pas très élégant, mais cela fait le travail, en utilisant un dictionnaire intermédiaire.
[{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}]
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
filter_dict = [{'11': 2}, {'33': 2}]
tmp = {k: d[k] for d in filter_dict for k in d} # {'11': 2, '33': 2}
out = []
for d in dd:
id = [*d][0]
if id not in tmp:
out.append(d)
tmp[id] = 0
elif tmp[id]:
out.append(d)
tmp[id] -= 1
else:
del tmp[id]
print(out)
Nicee, cela fonctionne comme prévu. Merci! Pouvons-nous changer les résultats en une liste d'identifiants similaires? comme: res = [{'11': [{'xx': '259', 'priority': '1', 'channels': '55'}, {'xx': '260', ' priority ':' 2 ',' channels ':' 35 '}]}, {' 22 ': [{' xx ':' 300 ',' priority ':' 1 ',' channels ':' 40 '}] }, {'33': [{'xx': '400', 'priority': '1', 'channels': '40'}, {'xx': '500', 'priority': '2' , 'canaux': '30'}]}]
Vous pouvez utiliser defaultdict pour vous aider avec ce
[{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11':{'xx':'260','priority': '2', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels':'40'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}]
Output
from collections import defaultdict
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
res_each = defaultdict(list)
filter_dict = [{'11': 2}, {'33': 2}]
filter_map = {list(i.keys())[0]: list(i.values())[0] for i in filter_dict}
for i in dd:
res_each[list(i.keys())[0]].append(i)
res = []
for i in [sorted(v, key=lambda x: int(list(x.values())[0]['priority']))[:filter_map.get(k, 1)] for k, v in res_each.items()]:
res.extend(i)
print(res)
Frais. J'aime vraiment ça, pouvons-nous regrouper les éléments d'identification similaires? une sortie comme: result = [{'11': [{'xx': '259', 'priority': '1', 'channels': '55'}, {'xx': '260' , 'priority': '2', 'channels': '35'}]}, {'22': [{'xx': '300', 'priority': '1', 'channels': '40' }]}, {'33': [{'xx': '400', 'priority': '1', 'channels': '40'}, {'xx': '500', 'priority': ' 2 ',' chaînes ':' 30 '}]}]
Vous pouvez par imprimer ([{list (i [0] .keys ()) [0]: sum ([list (y.values ()) for y in i], [])} for i in [ sorted (v, key = lambda x: list (x.values ()) [0] ['priority']) [: filter_map.get (k, 1)] pour k, v dans res_each.items ()]]) à la fin mais ce n'est pas si joli.
la solution casse s'il y a plus de 4 éléments du même id .
J'ai modifié le code et maintenant la sortie est [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}}, {'11 ': {' xx ':' 260 ',' priority ':' 2 ',' channels ':' 35 '}}, {' 22 ': {' xx ':' 300 ',' priority ':' 1 ' , 'channels': '40'}}, {'33': {'xx': '400', 'priority': '1', 'channels': '40'}}, {'33': {' xx ':' 500 ',' priority ':' 2 ',' channels ':' 30 '}}] basé sur le nouveau cas.
Je suppose que dd n'est pas du tout trié. J'espère que cela vous aidera.
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
# firstly sorted by key, then sorted by priority
dd = sorted(dd, key=lambda e: (list(e.keys())[0], int(list(e.values())[0]['priority'])))
filter_dict = [{'11': 2}, {'33': 2}]
filter_dict = {k:v for elem in filter_dict for k,v in elem.items()}
res = []
for i in dd:
key = list(i.keys())[0]
if key in filter_dict:
if filter_dict[key] > 0:
res.append(i)
filter_dict[key] -= 1
else:
res.append(i)
filter_dict[key] = 0
for i in res:
print(i)
@Sorn Ninh, il échoue avec si la priorité est 11 il semble qu'il ne se compare pas comme int . J'ai modifié ma question pour montrer le cas d'utilisation.
@LeeChun ouais, convertissez simplement 'priority' en type int. J'ai mis à jour la réponse
cela a fonctionné pour moi:
[{'11': [{'xx': '259', 'priority': '1', 'channels': '55'}, {'xx': '260', 'priority': '2', 'channels': '35'}]}, {'22': [{'xx': '300', 'priority': '1', 'channels': '40'}]}, {'33': [{'xx': '400', 'priority': '1', 'channels': '40'}, {'xx': '500', 'priority': '2', 'channels': '30'}]}]
Output
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '4', 'channels': '35'}},
{'11': {'xx': '260', 'priority': '9', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '11', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
filter_dict = [{'11': 2}, {'33': 2}]
res = []
middle_dict = {}
position = 0
first = True
def sortSecond(val):
return val[0]
for dd_one_dict in dd:
for dict_id, sub_dict in dd_one_dict.items():
if middle_dict.get(dict_id,False):
middle_dict[dict_id].append((int(sub_dict['priority']),position))
else:
middle_dict[dict_id] = [(int(sub_dict['priority']),position)]
position += 1
middle_dict[dict_id].sort(key = sortSecond)
external_counter = 0
for one_key in middle_dict.keys():
internal_counter = 2
for items in middle_dict[one_key]:
if first:
res.append({one_key:[dd[items[1]][one_key]]})
first = False
else:
for filter_one_dic in filter_dict:
if one_key == list(filter_one_dic.keys())[0]:
if internal_counter <= filter_one_dic[list(filter_one_dic.keys())[0]]:
res[external_counter][one_key].append(dd[items[1]][one_key])
internal_counter += 1
else:
break
first = True
external_counter += 1
print(res)
EDIT:
Voici une approche plus générale qui modifient également le format
{'11': {'xx': '259', 'priority': '1', 'channels': '55'}}
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}}
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}}
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}}
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}
Sortie:
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
filter_dict = [{'11': 2}, {'33': 2}]
res = []
for dd_one_dic in dd:
for dir_id, priority in dd_one_dic.items():
if priority['priority'] == '1':
res.append(dd_one_dic)
else:
for filter_one_dic in filter_dict:
if dir_id == list(filter_one_dic.keys())[0]:
if int(priority['priority']) <= filter_one_dic[list(filter_one_dic.keys())[0]]:
res.append(dd_one_dic)
print(*res, sep = '\n')
Ansres Lara Viana Pouvez-vous modifier votre réponse pour regrouper les éléments d'identification similaires? une sortie comme: result = [{'11': [{'xx': '259', 'priority': '1', 'channels': '55'}, {'xx': '260' , 'priority': '2', 'channels': '35'}]}, {'22': [{'xx': '300', 'priority': '1', 'channels': '40' }]}, {'33': [{'xx': '400', 'priority': '1', 'channels': '40'}, {'xx': '500', 'priority': ' 2 ',' chaînes ':' 30 '}]}]
@LeeChun J'ai fait un changement de format et ajouté un peu plus de généralisation au code, mais je vous recommande de le tester soigneusement avec différents ensembles de données.
ddest-il trié par id et priorité comme dans l'exemple?@ywbaek
jjest trié parprioritémais leidpeut varier, c'est-à-dire qu'un autre identifiant après33pourrait être2ou2000.J'ai fait ce mauvais one-liner:
[x pour x dans dd if int (next (iter (x.values ())) ['priority']) <= {k: v pour d dans filter_dict pour k, v dans d.items ()}. get (next (iter (x)), 1)]. Cela fonctionne, mais vous ne devriez pas l’utiliser.Pouvez-vous utiliser d'autres bibliothèques comme les pandas?