11 votes

Méthode pythonique pour créer un dictionnaire à partir d'une liste où les clés sont les éléments qui se trouvent dans une autre liste et les valeurs sont les éléments entre les clés.

Considérant que j'ai deux listes comme :

l1 = ['a', 'c', 'b', 'e', 'f', 'd']
l2 = [
    'x','q','we','da','po',
    'a', 'el1', 'el2', 'el3', 'el4',
    'b', 'some_other_el_1', 'some_other_el_2',
    'c', 'another_element_1', 'another_element_2',
    'd', '', '', 'another_element_3', 'd4'
]

et j'ai besoin de créer un dictionnaire où les clés sont les éléments de la deuxième liste qui sont trouvés dans la première et les valeurs sont des listes d'éléments trouvés entre les "clés", par exemple :

result = {
    'a': ['el1', 'el2', 'el3', 'el4'],
    'b': ['some_other_el_1', 'some_other_el_2'],
    'c': ['another_element_1', 'another_element_2'],
    'd': ['', '', 'another_element_3', 'd4']
}

Quelle est la façon la plus pythique de faire cela ?

Actuellement, je fais ceci :

# I'm not sure that the first element in the second list
# will also be in the first so I have to create a key
k = ''
d[k] = []
for x in l2:
    if x in l1:
        k = x
        d[k] = []
    else:
        d[k].append(x)

Mais je suis certain que ce n'est pas la meilleure façon de faire et que ce n'est pas très joli :)

Éditer : Je dois également mentionner qu'aucune liste n'est nécessairement ordonnée et que la seconde liste ne doit pas non plus commencer par un élément de la première.

1voto

Eric Duminil Points 38857

Votre code est lisible, fait le travail et est raisonnablement efficace. Il n'y a pas besoin de changer grand chose !

Vous pourriez utiliser des noms de variables plus descriptifs et remplacer l1 avec un set pour une recherche plus rapide :

keys = ('a', 'c', 'b', 'e', 'f', 'd')
keys_and_values = [
    'x','q','we','da','po',
    'a', 'el1', 'el2', 'el3', 'el4',
    'b', 'some_other_el_1', 'some_other_el_2',
    'c', 'another_element_1', 'another_element_2',
    'd', '', '', 'another_element_3', 'd4'
]

current_key = None
result = {}
for x in keys_and_values:
    if x in keys:
        current_key = x
        result[current_key] = []
    elif current_key:
        result[current_key].append(x)

print(result)
# {'a': ['el1', 'el2', 'el3', 'el4'],
#  'c': ['another_element_1', 'another_element_2'],
#  'b': ['some_other_el_1', 'some_other_el_2'],
#  'd': ['', '', 'another_element_3', 'd4']}

1voto

Acccumulation Points 1642
 def find_index():
    idxs = [l2.index(i) for i in set(l1).intersection(set(l2))]
    idxs.sort()
    idxs+= [len(l2)+1]
    res = {l2[idxs[i]]: list(l2[idxs[i]+1: idxs[i+1]]) for i in range(len(idxs)-1)}
    return(res)

Comparaison des méthodes, à l'aide du test de Justengel :
justengel
run_comp : .455
run_other : .244
mkrieger1
group_by_keys : .160
moi
trouver_index : .068

Notez que ma méthode ignore les clés qui n'apparaissent pas. l2 et ne gère pas les cas où les clés apparaissent plus d'une fois dans la liste des clés. l2 . Ajout de listes vides pour les clés qui n'apparaissent pas dans la base de données de la l2 peut être fait par {**res, **{key: [] for key in set(l1).difference(set(l2))}} ce qui porte le temps à 0,105.

1voto

Boris Points 1440

Encore plus propre que le tournage l1 en un set utilisez les clés du dictionnaire que vous construisez. Comme ceci

d = {x: [] for x in l1}
k = None

for x in l2:
    if x in d:
        k = x
    elif k is not None:
        d[k].append(x)

Cela est dû au fait que (dans le pire des cas) votre code itèrerait sur toutes les valeurs dans le fichier l1 pour chaque valeur dans l2 sur le if x in l1: la ligne, car vérifier si une valeur est in une liste prend un temps linéaire . Vérifier si une valeur est in les clés d'un dictionnaire est un temps constant dans le cas moyen ( même avec set s comme déjà suggéré par Eric Duminil ).

J'ai mis k a None et le vérifier parce que votre code aurait retourné d con '': ['x','q','we','da','po'] ce qui n'est vraisemblablement pas ce que vous voulez. Cela suppose l1 ne peut pas contenir None .

Ma solution suppose également qu'il n'y a pas de problème à ce que le dictionnaire résultant contienne des clés avec des listes vides s'il y a des éléments dans le fichier l1 qui n'apparaissent jamais dans l2 . Si cela ne vous convient pas, vous pouvez les enlever à la fin avec

final_d = {k: v for k, v in d.items() if v}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X