J'ai une liste d'ID entiers triés comme
{1: ["A", "B"], 2: ["A", "B"], 10: ["N/A", "B"], 15: ["B", "N/A"],
16: ["A", "A"], 17: ["B", "B"], 20: ["N/A", "N/A"], 34: ["B", "B"]}
J'ai un tuple (tuple1) de tuples de codes à côté d'un ID trié par ID comme
((1, "B"), (2, "B"), (10, "B"), (16, "A"), (17, "B"), (34, "B"), ...)
J'ai un autre tuple (tuple2) de tuples dans le même format comme
((1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), (34, "B"), ...)
Je veux combiner les tuples dans un dictionnaire où la clé est le ID et la valeur sont une liste contenant leur code de tuple1 et leur code de tuple2 dans cet ordre. Si l'ID existe dans la liste d'ID mais pas dans le tuple, la valeur doit être "N/A".
Par conséquent, en utilisant les données ci-dessus, les éléments suivants doivent être produits:
[1, 2, 10, 15, 16, 17, 20, 34, ...]
J'ai passé un certain temps à réfléchir à ce problème mais je ne peux pas trouver de solution. Si quelqu'un pouvait m'aider à comprendre comment le faire fonctionner en Python, ce serait extrêmement utile.
Merci.
MODIFIER: Ce n'est pas un doublon strong >, ce problème est considérablement plus complexe.
5 Réponses :
Si vous transformez votre tuple de tuples dans un dictionnaire, ce sera beaucoup plus facile. Utilisez get pour définir une valeur par défaut pour votre dictionnaire si la clé est absente:
ids = [1, 2, 10, 15, 16, 17, 20, 34]
tup1 = ((1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), (34, "B"))
tup2 = ((1, "B"), (2, "B"), (10, "B"), (16, "A"), (17, "B"), (34, "B"))
tup1 = dict(tup1)
tup2 = dict(tup2)
{k: [tup1.get(k, 'N/A'), tup2.get(k, 'N/A')] for k in ids}
Je suppose que vous vouliez dire tup1 = (1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), ( 34, "B") , tup1 = dict ((x, y) pour x, y dans tup1) . Cependant, j'obtiens toujours l'erreur "AttributeError: l'objet 'dict' n'a pas d'attribut 'getitem'".
@JackP J'ai utilisé par erreur getitem lors de ma première publication. Cela devrait être get .
Et je voulais créer un dictionnaire à partir des tuples. Il vous permet d'utiliser get et d'attribuer une valeur par défaut: 'N / A' .
Cela fonctionne sans l'expression de dict de compréhension de liste supplémentaire maintenant que vous avez ajouté la parenthèse supplémentaire. Merci.
Bon à entendre. J'ai quand même clarifié mon intention dans le code.
Voici une solution possible à cela:
>>> merge_d
defaultdict(<class 'list'>, {1: ['A', 'B'], 2: ['A', 'B'], 10: ['N/A', 'B'], 15: ['B', 'N/A'], 16: ['A', 'A'], 17: ['B', 'B'], 20: ['N/A', 'N/A'], 34: ['B', 'B']})
Le dict résultant contiendra:
from collections import defaultdict
keys = [1, 2, 10, 15, 16, 17, 20, 34]
t1 = ((1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), (34, "B"))
t2 = ((1, "B"), (2, "B"), (10, "B"), (16, "A"), (17, "B"), (34, "B"))
merge_d = defaultdict(list)
for d in map(dict, (t1, t2)):
for k in keys:
merge_d[k].append(d.get(k, "N/A"))
Merci mais je pense que c'est un peu plus lent que la solution de busybear.
C'est un peu dégoûtant, mais vous pouvez le faire sans convertir en dictionnaire:
myList = [1, 2, 10, 15, 16, 17, 20, 34]
tuples1 = ((1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), (34, "B"))
tuples2 = ((1, "B"), (2, "B"), (10, "B"), (16, "A"), (17, "B"), (34, "B"))
myDict = {}
for i in myList:
myDict[i] = ["N/A","N/A"]
for t in tuples1:
if(t[0]) in myList:
for key in myDict:
if key == t[0]:
myDict[key][0] = t[1]
for t in tuples2:
if(t[0]) in myList:
for key in myDict:
if key == t[0]:
myDict[key][1] = t[1]
print(myDict)
Donne:
{1: ['A', 'B'], 2: ['A', 'B'], 10: ['N / A', 'B'], 15: ['B', ' N / A '], 16: [' A ',' A '], 17: [' B ',' B '], 20: [' N / A ',' N / A '], 34: [' B ',' B ']}
Merci. Désolé si je n'étais pas clair, mais l'identifiant ne devrait être présent dans le dictionnaire final que s'il est présent dans la liste d'identifiants donnée.
@JackP Pas de problème. Je vais mettre à jour la réponse, vous utilisez simplement les éléments de la liste au lieu d'un générateur.
Ah oui cela semble avoir fonctionné grâce. Bien que je pense que c'est un peu plus lent que la solution de busybear.
Cela peut être fait d'une autre manière!
lis=[1, 2, 10, 15, 16, 17, 20, 34]
tuple1=((1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), (34, "B"))
tuple2=((1, "B"), (2, "B"), (10, "B"), (16, "A"), (17, "B"), (34, "B"))
z={**dict.fromkeys(lis,'N/A'), **dict(tuple1)}
y={**dict.fromkeys(lis, 'N/A'), **dict(tuple2)}
ds = [z, y]
d = {}
for k in y.keys():
d[k] = list(d[k] for d in ds)
Merci mais je pense que c'est un peu plus lent que la solution de busybear.
Mes deux cents: une solution en une ligne, basée sur la réponse de @ busybear, capable de gérer un nombre arbitraire de tuples:
ids = [1, 2, 10, 15, 16, 17, 20, 34]
vals = (
((1, "A"), (2, "A"), (15, "B"), (16, "A"), (17, "B"), (34, "B"),),
((1, "B"), (2, "B"), (10, "B"), (16, "A"), (17, "B"), (34, "B"),),
)
d = {i: [d.get(i, 'N/A') for d in map(dict, vals)] for i in ids}
Double possible de Convertir deux listes en un dictionnaire en Python
@JordanSinger Je pense que c'est plus complexe que ça.
@JordanSinger Veuillez lire la question.
Vos tuples / listes sont-ils énormes (à la recherche d'une solution rapide) ou avez-vous juste besoin de une solution?
@JackP est-ce que toutes vos listes sont triées par ID comme elles le sont dans votre question?
@StephenCowley Ils ne sont pas énormes mais ils mesurent environ 400-2000 chacun, donc une solution raisonnablement rapide serait appréciée.
@wpercy Oui, ils le sont.