J'ai X nombre de listes, par exemple:
{'potato': 2, 'pie': 2, 'chicken': 1, 'donkey': 1}
Je veux vérifier combien de liste un terme apparaît-il:
Par exemple: p >
Avec les deux listes ci-dessus, je voudrais que le résultat soit:
{'potato': 3, 'pie': 2, 'chicken': 2, 'donkey': 1}
Ma tentative, mais je le faisais complètement mal et je devenais confus et si j'étais égal en adoptant la bonne approche:
x = ['potato', 'pie']
z = ['chicken','chicken','pie','donkey','potato','potato']
list_final = x + z
dict_final = {}
for item in list_final:
if item in dict_final.keys():
dict_final.update({item:(dict_final.get(item) + 1)})
else:
dict_final.update({item:1})
print(dict_final)
J'ai essayé ceci, mais cela compte juste toutes les fois où il apparaît dans la liste:
(potato,2) (pie,2) (chicken,1) - chicken is only one because it appears only in list two, not in list one. (donkey,1)
mais j'essaye d'obtenir:
[potato, pie] [chicken,chicken,pie,donkey,potato,potato]
3 Réponses :
Vous devriez parcourir le ensemble d'une liste de vos articles pour ne pas compter deux fois. De plus, vous devrez parcourir tous les éléments et sur vos listes:
list_final = [(i, sum([i in lst for lst in (x, z)])) for i in items]
dict_final = {i: sum([i in lst for lst in (x, z)]) for i in items}
Pour créer une liste de tuples que vous pourriez faire
list_final = []
for i in items:
cntr = sum([i in lst for lst in (x, z)])
list_final.append((i, cntr))
... et pour les fans des oneliners:
x = ['potato', 'pie']
z = ['chicken','chicken','pie','donkey','potato','potato']
items = set(x + z)
dict_final = {}
for i in items:
for lst in [x, z]:
if i in lst:
dict_final[i] = dict_final.get(i, 0) + 1
# {'chicken': 1, 'donkey': 1, 'potato': 2, 'pie': 2}
si vous le rendez plus fonctionnel)
from collections import Counter
from functools import reduce
x = ['potato', 'pie']
y = ['chicken','chicken','pie','donkey','potato','potato']
all_lists = [x, y]
dict(Counter(reduce(lambda x, y: x + list(set(y)), all_lists, [])).most_common())
# {'potato': 2, 'pie': 2, 'donkey': 1, 'chicken': 1}
... et si OP veut avoir un dict comme ils l'ont fait dans l'exemple de code publié de la question, ils n'auront qu'à l'appliquer à la dernière commande: dict (Counter ( ... .most_common ())
juste pour l'intérêt: voici les timings des solutions disponibles jusqu'à présent:
import timeit
rep = 100000
n = 5
setup = """
from collections import Counter
from functools import reduce
x = ['potato', 'pie']
z = ['chicken','chicken','pie','donkey','potato','potato']
all_lists = [x, z]
items = set(x + z)
list_final = []
dict_final = {}
"""
fcts = {
'Counter/reduce':
'Counter(reduce(lambda x, z: x + list(set(z)), all_lists, [])).most_common()',
'Counter/reduce into dict':
'dict(Counter(reduce(lambda x, z: x + list(set(z)), all_lists, [])).most_common())',
'double for loop dict':
'''for i in items:
for lst in (x, z):
if i in lst:
dict_final[i] = dict_final.get(i, 0) + 1
''',
'for loop LC into dict':
'''for i in items:
cntr = sum([i in lst for lst in (x, z)])
dict_final[i] = cntr''',
'for loop LC into list':
'''for i in items:
cntr = sum([i in lst for lst in (x, z)])
list_final.append((i, cntr))''',
'LC into LC':
'[(i, sum([1 for lst in (x, z) if i in lst])) for i in items]',
'LC into DC':
'{i: sum([i in lst for lst in (x, z)]) for i in items}'
}
L = max((len(k) for k in fcts.keys()))
results = []
for k, v in fcts.items():
print(f'timing {k}...')
tt = timeit.Timer(v, setup=setup)
t = min(tt.repeat(repeat=rep, number=n))
results.append((k, t))
for i, (k, t) in enumerate(sorted(results, key=lambda x: x[1])):
print(f'{i+1}. {k:{L}}: {t:.3}')
Code pour le timing:
1. double for loop dict : 8.1e-06 2. for loop LC into dict : 1.32e-05 3. LC into LC : 1.37e-05 4. for loop LC into list : 1.41e-05 5. LC into DC : 1.41e-05 6. Counter/reduce : 2.47e-05 7. Counter/reduce into dict: 2.64e-05
Si je comprends bien, vous pouvez utiliser set () pour supprimer les doublons de la liste z et vous obtiendrez la réponse attendue.