1
votes

Rechercher efficacement une valeur dans une liste de dictionnaires

J'ai une liste de dictionnaires comme

playerStats['Mohamed Salah']
{'id': 5178.0, 'stats': [{'name': 'accurate_back_zone_pass', 'additionalInfo': {}, 'description': 'Todo: accurate_back_zone_pass', 'value': 70.0}, {'name': 'accurate_chipped_pass', 'additionalInfo': {}, 'description': 'Todo: accurate_chipped_pass', 'value': 10.0}, {'name': 'accurate_corners_intobox', 'additionalInfo': {}, 'description': 'Todo: accurate_corners_intobox', 'value': 6.0}, {'name': 'accurate_cross', 'additionalInfo': {}, 'description': 'Todo: accurate_cross', 'value': 11.0}, {'name': 'accurate_cross_nocorner', 'additionalInfo': {}, 'description': 'Todo: accurate_cross_nocorner', 'value': 5.0}, {'name': 'accurate_flick_on', 'additionalInfo': {}, 'description': 'Todo: accurate_flick_on', 'value': 5.0}, {'name': 'accurate_freekick_cross', 'additionalInfo': {}, 'description': 'Todo: accurate_freekick_cross', 'value': 0.0}, {'name': 'accurate_fwd_zone_pass', 'additionalInfo': {}, 'description': 'Todo: accurate_fwd_zone_pass', 'value': 377.0}, {'name': 'accurate_layoffs', 'additionalInfo': {}, 'description': 'Todo: accurate_layoffs', 'value': 19.0}, {'name': 'accurate_long_balls', 'additionalInfo': {}, 'description': 'Todo: accurate_long_balls', 'value': 7.0}, {'name': 'accurate_pass', 'additionalInfo': {}, 'description': 'Todo: accurate_pass', 'value': 436.0}, {'name': 'accurate_through_ball', 'additionalInfo': {}, 'description': 'Todo: accurate_through_ball', 'value': 8.0}, {'name': 'accurate_throws', 'additionalInfo': {}, 'description': 'Todo: accurate_throws', 'value': 3.0}, {'name': 'aerial_lost', 'additionalInfo': {}, 'description': 'Todo: aerial_lost', 'value': 32.0}, {'name': 'aerial_won', 'additionalInfo': {}, 'description': 'Todo: aerial_won', 'value': 9.0}, {'name': 'appearances', 'additionalInfo': {}, 'description': 'Todo: appearances', 'value': 21.0}, {'name': 'assist_penalty_won', 'additionalInfo': {}, 'description': 'Todo: assist_penalty_won', 'value': 1.0}, {'name': 'attempted_tackle_foul', 'additionalInfo': {}, 'description': 'Todo: attempted_tackle_foul', 'value': 5.0}, {'name': 'attempts_conceded_ibox', 'additionalInfo': {}, 'description': 'Todo: attempts_conceded_ibox', 'value': 95.0}, {'name': 'attempts_conceded_obox', 'additionalInfo': {}, 'description': 'Todo: attempts_conceded_obox', 'value': 61.0}, {'name': 'attempts_ibox', 'additionalInfo': {}, 'description': 'Todo: attempts_ibox', 'value': 50.0}, {'name': 'attempts_obox', 'additionalInfo': {}, 'description': 'Todo: attempts_obox', 'value': 19.0}, {'name': 'att_assist_openplay', 'additionalInfo': {}, 'description': 'Todo: att_assist_openplay', 'value': 34.0}, {'name': 'att_assist_setplay', 'additionalInfo': {}, 'description': 'Todo: att_assist_setplay', 'value': 3.0}, {'name': 'att_bx_centre', 'additionalInfo': {}, 'description': 'Todo: att_bx_centre', 'value': 23.0}, {'name': 'att_bx_left', 'additionalInfo': {}, 'description': 'Todo: att_bx_left', 'value': 2.0}, {'name': 'att_bx_right', 'additionalInfo': {}, 'description': 'Todo: att_bx_right', 'value': 10.0}, {'name': 'att_cmiss_high', 'additionalInfo': {}, 'description': 'Todo: att_cmiss_high', 'value': 2.0}, {'name': 'att_cmiss_left', 'additionalInfo': {}, 'description': 'Todo: att_cmiss_left', 'value': 2.0}, {'name': 'att_cmiss_right', 'additionalInfo': {}, 'description': 'Todo: att_cmiss_right', 'value': 3.0}, {'name': 'att_fastbreak', 'additionalInfo': {}, 'description': 'Todo: att_fastbreak', 'value': 6.0}, {'name': 'att_freekick_total', 'additionalInfo': {}, 'description': 'Todo: att_freekick_total', 'value': 1.0}, {'name': 'att_goal_high_centre', 'additionalInfo': {}, 'description': 'Todo: att_goal_high_centre', 'value': 1.0}, {'name': 'att_goal_high_left', 'additionalInfo': {}, 'description': 'Todo: att_goal_high_left', 'value': 1.0}, {'name': 'att_goal_low_centre', 'additionalInfo': {}, 'description': 'Todo: att_goal_low_centre', 'value': 4.0}, {'name': 'att_goal_low_left', 'additionalInfo': {}, 'description': 'Todo: att_goal_low_left', 'value': 5.0}, {'name': 'att_goal_low_right', 'additionalInfo': {}, 'description': 'Todo: att_goal_low_right', 'value': 2.0}, {'name': 'att_hd_target', 'additionalInfo': {}, 'description': 'Todo: att_hd_target', 'value': 3.0}, {'name': 'att_hd_total', 'additionalInfo': {}, 'description': 'Todo: att_hd_total', 'value': 3.0}, {'name': 'att_ibox_blocked', 'additionalInfo': {}, 'description': 'Todo: att_ibox_blocked', 'value': 7.0}, {'name': 'att_ibox_goal', 'additionalInfo': {}, 'description': 'Todo: att_ibox_goal', 'value': 13.0}, {'name': 'att_ibox_miss', 'additionalInfo': {}, 'description': 'Todo: att_ibox_miss', 'value': 12.0}, {'name': 'att_ibox_target', 'additionalInfo': {}, 'description': 'Todo: att_ibox_target', 'value': 18.0}, {'name': 'att_lf_goal', 'additionalInfo': {}, 'description': 'Todo: att_lf_goal', 'value': 11.0}, {'name': 'att_lf_target', 'additionalInfo': {}, 'description': 'Todo: att_lf_target', 'value': 11.0}, {'name': 'att_lf_total', 'additionalInfo': {}, 'description': 'Todo: att_lf_total', 'value': 56.0}, {'name': 'att_lg_centre', 'additionalInfo': {}, 'description': 'Todo: att_lg_centre', 'value': 1.0}, {'name': 'att_miss_high', 'additionalInfo': {}, 'description': 'Todo: att_miss_high', 'value': 4.0}, {'name': 'att_miss_high_left', 'additionalInfo': {}, 'description': 'Todo: att_miss_high_left', 'value': 3.0}, {'name': 'att_miss_high_right', 'additionalInfo': {}, 'description': 'Todo: att_miss_high_right', 'value': 1.0}, {'name': 'att_miss_left', 'additionalInfo': {}, 'description': 'Todo: att_miss_left', 'value': 4.0}, {'name': 'att_miss_right', 'additionalInfo': {}, 'description': 'Todo: att_miss_right', 'value': 6.0}, {'name': 'att_obox_blocked', 'additionalInfo': {}, 'description': 'Todo: att_obox_blocked', 'value': 10.0}, {'name': 'att_obox_miss', 'additionalInfo': {}, 'description': 'Todo: att_obox_miss', 'value': 6.0}, {'name': 'att_obox_target', 'additionalInfo': {}, 'description': 'Todo: att_obox_target', 'value': 3.0}, {'name': 'att_obx_centre', 'additionalInfo': {}, 'description': 'Todo: att_obx_centre', 'value': 16.0}, {'name': 'att_obx_right', 'additionalInfo': {}, 'description': 'Todo: att_obx_right', 'value': 2.0}, {'name': 'att_one_on_one', 'additionalInfo': {}, 'description': 'Todo: att_one_on_one', 'value': 2.0}, {'name': 'att_openplay', 'additionalInfo': {}, 'description': 'Todo: att_openplay', 'value': 58.0}, {'name': 'att_pen_goal', 'additionalInfo': {}, 'description': 'Todo: att_pen_goal', 'value': 2.0}, {'name': 'att_rf_goal', 'additionalInfo': {}, 'description': 'Todo: att_rf_goal', 'value': 2.0}, {'name': 'att_rf_target', 'additionalInfo': {}, 'description': 'Todo: att_rf_target', 'value': 7.0}, {'name': 'att_rf_total', 'additionalInfo': {}, 'description': 'Todo: att_rf_total', 'value': 10.0}, {'name': 'att_setpiece', 'additionalInfo': {}, 'description': 'Todo: att_setpiece', 'value': 3.0}, {'name': 'att_sv_high_centre', 'additionalInfo': {}, 'description': 'Todo: att_sv_high_centre', 'value': 1.0}, {'name': 'att_sv_high_left', 'additionalInfo': {}, 'description': 'Todo: att_sv_high_left', 'value': 1.0}, {'name': 'att_sv_low_centre', 'additionalInfo': {}, 'description': 'Todo: att_sv_low_centre', 'value': 8.0}, {'name': 'att_sv_low_left', 'additionalInfo': {}, 'description': 'Todo: att_sv_low_left', 'value': 5.0}, {'name': 'att_sv_low_right', 'additionalInfo': {}, 'description': 'Todo: att_sv_low_right', 'value': 6.0}, {'name': 'backward_pass', 'additionalInfo': {}, 'description': 'Todo: backward_pass', 'value': 151.0}, {'name': 'ball_recovery', 'additionalInfo': {}, 'description': 'Todo: ball_recovery', 'value': 61.0}, {'name': 'big_chance_created', 'additionalInfo': {}, 'description': 'Todo: big_chance_created', 'value': 13.0}, {'name': 'big_chance_missed', 'additionalInfo': {}, 'description': 'Todo: big_chance_missed', 'value': 11.0}, {'name': 'big_chance_scored', 'additionalInfo': {}, 'description': 'Todo: big_chance_scored', 'value': 8.0}, {'name': 'blocked_cross', 'additionalInfo': {}, 'description': 'Todo: blocked_cross', 'value': 2.0}, {'name': 'blocked_pass', 'additionalInfo': {}, 'description': 'Todo: blocked_pass', 'value': 25.0}, {'name': 'blocked_scoring_att', 'additionalInfo': {}, 'description': 'Todo: blocked_scoring_att', 'value': 17.0}, {'name': 'challenge_lost', 'additionalInfo': {}, 'description': 'Todo: challenge_lost', 'value': 5.0}, {'name': 'clean_sheet', 'additionalInfo': {}, 'description': 'Todo: clean_sheet', 'value': 9.0}, {'name': 'corner_taken', 'additionalInfo': {}, 'description': 'Todo: corner_taken', 'value': 23.0}, {'name': 'crosses_18yard', 'additionalInfo': {}, 'description': 'Todo: crosses_18yard', 'value': 8.0}, {'name': 'crosses_18yardplus', 'additionalInfo': {}, 'description': 'Todo: crosses_18yardplus', 'value': 4.0}, {'name': 'dispossessed', 'additionalInfo': {}, 'description': 'Todo: dispossessed', 'value': 72.0}, {'name': 'draws', 'additionalInfo': {}, 'description': 'Todo: draws', 'value': 3.0}, {'name': 'duel_lost', 'additionalInfo': {}, 'description': 'Todo: duel_lost', 'value': 143.0}, {'name': 'duel_won', 'additionalInfo': {}, 'description': 'Todo: duel_won', 'value': 80.0}, {'name': 'effective_blocked_cross', 'additionalInfo': {}, 'description': 'Todo: effective_blocked_cross', 'value': 2.0}, {'name': 'effective_clearance', 'additionalInfo': {}, 'description': 'Todo: effective_clearance', 'value': 2.0}, {'name': 'effective_head_clearance', 'additionalInfo': {}, 'description': 'Todo: effective_head_clearance', 'value': 1.0}, {'name': 'final_third_entries', 'additionalInfo': {}, 'description': 'Todo: final_third_entries', 'value': 36.0}, {'name': 'fouled_final_third', 'additionalInfo': {}, 'description': 'Todo: fouled_final_third', 'value': 12.0}, {'name': 'fouls', 'additionalInfo': {}, 'description': 'Todo: fouls', 'value': 15.0}, {'name': 'freekick_cross', 'additionalInfo': {}, 'description': 'Todo: freekick_cross', 'value': 4.0}, {'name': 'fwd_pass', 'additionalInfo': {}, 'description': 'Todo: fwd_pass', 'value': 114.0}, {'name': 'game_started', 'additionalInfo': {}, 'description': 'Todo: game_started', 'value': 20.0}, {'name': 'goals', 'additionalInfo': {}, 'description': 'Todo: goals', 'value': 13.0}, {'name': 'goals_conceded', 'additionalInfo': {}, 'description': 'Todo: goals_conceded', 'value': 9.0}, {'name': 'goals_conceded_ibox', 'additionalInfo': {}, 'description': 'Todo: goals_conceded_ibox', 'value': 9.0}, {'name': 'goals_openplay', 'additionalInfo': {}, 'description': 'Todo: goals_openplay', 'value': 9.0}, {'name': 'goal_assist', 'additionalInfo': {}, 'description': 'Todo: goal_assist', 'value': 7.0}, {'name': 'goal_assist_deadball', 'additionalInfo': {}, 'description': 'Todo: goal_assist_deadball', 'value': 1.0}, {'name': 'goal_assist_intentional', 'additionalInfo': {}, 'description': 'Todo: goal_assist_intentional', 'value': 7.0}, {'name': 'goal_assist_openplay', 'additionalInfo': {}, 'description': 'Todo: goal_assist_openplay', 'value': 5.0}, {'name': 'goal_assist_setplay', 'additionalInfo': {}, 'description': 'Todo: goal_assist_setplay', 'value': 2.0}, {'name': 'goal_fastbreak', 'additionalInfo': {}, 'description': 'Todo: goal_fastbreak', 'value': 1.0}, {'name': 'hand_ball', 'additionalInfo': {}, 'description': 'Todo: hand_ball', 'value': 1.0}, {'name': 'head_clearance', 'additionalInfo': {}, 'description': 'Todo: head_clearance', 'value': 1.0}, {'name': 'head_pass', 'additionalInfo': {}, 'description': 'Todo: head_pass', 'value': 25.0}, {'name': 'interception', 'additionalInfo': {}, 'description': 'Todo: interception', 'value': 4.0}, {'name': 'interception_won', 'additionalInfo': {}, 'description': 'Todo: interception_won', 'value': 4.0}, {'name': 'leftside_pass', 'additionalInfo': {}, 'description': 'Todo: leftside_pass', 'value': 216.0}, {'name': 'long_pass_own_to_opp', 'additionalInfo': {}, 'description': 'Todo: long_pass_own_to_opp', 'value': 13.0}, {'name': 'long_pass_own_to_opp_success', 'additionalInfo': {}, 'description': 'Todo: long_pass_own_to_opp_success', 'value': 10.0}, {'name': 'losses', 'additionalInfo': {}, 'description': 'Todo: losses', 'value': 1.0}, {'name': 'mins_played', 'additionalInfo': {}, 'description': 'Todo: mins_played', 'value': 1759.0}, {'name': 'offtarget_att_assist', 'additionalInfo': {}, 'description': 'Todo: offtarget_att_assist', 'value': 14.0}, {'name': 'ontarget_att_assist', 'additionalInfo': {}, 'description': 'Todo: ontarget_att_assist', 'value': 30.0}, {'name': 'ontarget_scoring_att', 'additionalInfo': {}, 'description': 'Todo: ontarget_scoring_att', 'value': 34.0}, {'name': 'open_play_pass', 'additionalInfo': {}, 'description': 'Todo: open_play_pass', 'value': 556.0}, {'name': 'overrun', 'additionalInfo': {}, 'description': 'Todo: overrun', 'value': 7.0}, {'name': 'passes_left', 'additionalInfo': {}, 'description': 'Todo: passes_left', 'value': 47.0}, {'name': 'passes_right', 'additionalInfo': {}, 'description': 'Todo: passes_right', 'value': 119.0}, {'name': 'penalty_won', 'additionalInfo': {}, 'description': 'Todo: penalty_won', 'value': 3.0}, {'name': 'pen_area_entries', 'additionalInfo': {}, 'description': 'Todo: pen_area_entries', 'value': 93.0}, {'name': 'poss_lost_all', 'additionalInfo': {}, 'description': 'Todo: poss_lost_all', 'value': 323.0}, {'name': 'poss_lost_ctrl', 'additionalInfo': {}, 'description': 'Todo: poss_lost_ctrl', 'value': 323.0}, {'name': 'poss_won_att_3rd', 'additionalInfo': {}, 'description': 'Todo: poss_won_att_3rd', 'value': 20.0}, {'name': 'poss_won_def_3rd', 'additionalInfo': {}, 'description': 'Todo: poss_won_def_3rd', 'value': 14.0}, {'name': 'poss_won_mid_3rd', 'additionalInfo': {}, 'description': 'Todo: poss_won_mid_3rd', 'value': 27.0}, {'name': 'put_through', 'additionalInfo': {}, 'description': 'Todo: put_through', 'value': 25.0}, {'name': 'rightside_pass', 'additionalInfo': {}, 'description': 'Todo: rightside_pass', 'value': 92.0}, {'name': 'shot_fastbreak', 'additionalInfo': {}, 'description': 'Todo: shot_fastbreak', 'value': 6.0}, {'name': 'shot_off_target', 'additionalInfo': {}, 'description': 'Todo: shot_off_target', 'value': 18.0}, {'name': 'successful_final_third_passes', 'additionalInfo': {}, 'description': 'Todo: successful_final_third_passes', 'value': 261.0}, {'name': 'successful_open_play_pass', 'additionalInfo': {}, 'description': 'Todo: successful_open_play_pass', 'value': 419.0}, {'name': 'successful_put_through', 'additionalInfo': {}, 'description': 'Todo: successful_put_through', 'value': 6.0}, {'name': 'total_att_assist', 'additionalInfo': {}, 'description': 'Todo: total_att_assist', 'value': 44.0}, {'name': 'total_back_zone_pass', 'additionalInfo': {}, 'description': 'Todo: total_back_zone_pass', 'value': 82.0}, {'name': 'total_chipped_pass', 'additionalInfo': {}, 'description': 'Todo: total_chipped_pass', 'value': 30.0}, {'name': 'total_clearance', 'additionalInfo': {}, 'description': 'Todo: total_clearance', 'value': 2.0}, {'name': 'total_contest', 'additionalInfo': {}, 'description': 'Todo: total_contest', 'value': 61.0}, {'name': 'total_corners_intobox', 'additionalInfo': {}, 'description': 'Todo: total_corners_intobox', 'value': 20.0}, {'name': 'total_cross', 'additionalInfo': {}, 'description': 'Todo: total_cross', 'value': 36.0}, {'name': 'total_cross_nocorner', 'additionalInfo': {}, 'description': 'Todo: total_cross_nocorner', 'value': 16.0}, {'name': 'total_distance_in_m', 'additionalInfo': {}, 'description': 'Todo: total_distance_in_m', 'value': 10282.4443359375}, {'name': 'total_fastbreak', 'additionalInfo': {}, 'description': 'Todo: total_fastbreak', 'value': 9.0}, {'name': 'total_final_third_passes', 'additionalInfo': {}, 'description': 'Todo: total_final_third_passes', 'value': 363.0}, {'name': 'total_flick_on', 'additionalInfo': {}, 'description': 'Todo: total_flick_on', 'value': 13.0}, {'name': 'total_fwd_zone_pass', 'additionalInfo': {}, 'description': 'Todo: total_fwd_zone_pass', 'value': 527.0}, {'name': 'total_launches', 'additionalInfo': {}, 'description': 'Todo: total_launches', 'value': 2.0}, {'name': 'total_layoffs', 'additionalInfo': {}, 'description': 'Todo: total_layoffs', 'value': 23.0}, {'name': 'total_long_balls', 'additionalInfo': {}, 'description': 'Todo: total_long_balls', 'value': 15.0}, {'name': 'total_offside', 'additionalInfo': {}, 'description': 'Todo: total_offside', 'value': 18.0}, {'name': 'total_pass', 'additionalInfo': {}, 'description': 'Todo: total_pass', 'value': 573.0}, {'name': 'total_pull_back', 'additionalInfo': {}, 'description': 'Todo: total_pull_back', 'value': 1.0}, {'name': 'total_scoring_att', 'additionalInfo': {}, 'description': 'Todo: total_scoring_att', 'value': 69.0}, {'name': 'total_sub_off', 'additionalInfo': {}, 'description': 'Todo: total_sub_off', 'value': 6.0}, {'name': 'total_sub_on', 'additionalInfo': {}, 'description': 'Todo: total_sub_on', 'value': 1.0}, {'name': 'total_tackle', 'additionalInfo': {}, 'description': 'Todo: total_tackle', 'value': 10.0}, {'name': 'total_through_ball', 'additionalInfo': {}, 'description': 'Todo: total_through_ball', 'value': 11.0}, {'name': 'total_throws', 'additionalInfo': {}, 'description': 'Todo: total_throws', 'value': 5.0}, {'name': 'touches', 'additionalInfo': {}, 'description': 'Todo: touches', 'value': 957.0}, {'name': 'touches_in_opp_box', 'additionalInfo': {}, 'description': 'Todo: touches_in_opp_box', 'value': 165.0}, {'name': 'turnover', 'additionalInfo': {}, 'description': 'Todo: turnover', 'value': 59.0}, {'name': 'unsuccessful_touch', 'additionalInfo': {}, 'description': 'Todo: unsuccessful_touch', 'value': 59.0}, {'name': 'was_fouled', 'additionalInfo': {}, 'description': 'Todo: was_fouled', 'value': 21.0}, {'name': 'wins', 'additionalInfo': {}, 'description': 'Todo: wins', 'value': 17.0}, {'name': 'won_contest', 'additionalInfo': {}, 'description': 'Todo: won_contest', 'value': 41.0}, {'name': 'won_corners', 'additionalInfo': {}, 'description': 'Todo: won_corners', 'value': 23.0}, {'name': 'won_tackle', 'additionalInfo': {}, 'description': 'Todo: won_tackle', 'value': 5.0}]}

Comment puis-je déterminer efficacement si la liste a un dictionnaire avec dic ['name'] est 'objectifs' par exemple?

Une solution:

import numpy
import time

playerStats = numpy.load("/home/asus/Arief_tempo/others/Python/PL_data/players_stats.npy").item()
playerGoals = {}

a = time.perf_counter()
for name in playerStats.keys():
    lookup = {d['name']: d['value'] for d in playerStats[name]['stats']}
    try:        
        playerGoals[name] = int(lookup['goals'])
    except:
        playerGoals[name] = 0

print(time.perf_counter() - a)

La liste x est une statistique pour un joueur de football. Ainsi, un joueur qui n'a marqué aucun but n'aura pas de dictionnaire avec dic ['name'] est 'goals'.

playerStats = [....] , chaque élément de playerStats a une forme similaire à x , mais peut ne pas avoir de dictionnaire avec une valeur d'objectifs. p>

Il y aura environ 800 recherches


Une solution réelle utilisant la réponse de @ ggorlen

value = None
for dic in x:
        if dic['name'] == 'goals':
            value = int(dic['value'])
            break

Voici un exemple réel d'élément dans playerStats , le x que j'ai mentionné ci-dessus peut être associé à playerStats ['Mohamed Salah'] ['stats '] , l' 'id' ne sera pas utilisé ici. Il a des «buts», mais les autres joueurs peuvent ne pas avoir de «buts» comme clé.

x = [{'name': 'attack', 'value': 10}, {'name': 'attack_side', 'value': 12}, ..., \
{'name': 'goals', 'value': 5}, ........]


10 commentaires

Ce que vous avez déjà, c'est une bonne solution efficace.


Il n'y a pas de moyen plus efficace. Les objets de liste nécessitent un temps O (N) pour vérifier leur confinement, bien que, si la liste est triée, vous pouvez utiliser la recherche de bissection pour le faire au moment de la connexion. Vous pouvez utiliser un dict pour le faire en O (1)


Copie possible de la liste Python de recherche de dictionnaires


Je pense que cela vaut la peine de vous demander si vous allez rechercher cela une fois ou si vous allez faire la recherche des millions de fois. Si ce n'est qu'une seule fois, votre solution (ainsi que les solutions affichées ci-dessous) conviennent. Si vous envisagez d'effectuer de nombreuses recherches sur les mêmes données, vous devriez envisager de construire un mappage de la valeur de nom -> et d'utiliser cela pour votre table de recherche plutôt que le liste.


@mgilson je vais le faire pour de nombreuses autres listes similaires


@AriefAnbiya - Si ce ne sont pas les mêmes listes, alors peut-être que vous n'avez pas de chance à moins que vous ne puissiez persuader le producteur de ces listes de vous les donner dans un format différent.


@mgilson il y aura une liste des statistiques des joueurs de football, la statistique de chaque joueur est aussi une liste contenant des dictionnaires pour chaque type de statistique (buts, passes décisives, passes, etc.), mais un joueur sans but n'aura pas de dictionnaire pour les statistiques d'objectifs


@AriefAnbiya il peut y avoir un problème sous-jacent avec la conception de votre code / application si vous stockez des données comme celle-ci et que vous devez continuer à les rechercher en utilisant cette méthode pour des listes plus similaires . Puis-je vous demander si vous le stockez de cette façon ou êtes-vous simplement en train d'analyser des données provenant d'une autre source?


@AriefAnbiya semble que vous devriez reconcevoir vos structures de données, car une liste de dictées est en quelque sorte le pire des deux mondes


@AriefAnbiya Je pense qu'une classe pourrait être une bonne idée ici?


3 Réponses :


2
votes

Essayez quelque chose comme:

Code:

{'name': 'goals', 'value': 5}
None

Cela utilise une expression de générateur pour parcourir la liste et renvoie la première instance correspondante, ou Aucune si rien ne correspond.

Code de test:

data = [
    {'name': 'attack', 'value': 10},
    {'name': 'attack_side', 'value': 12},
    {'name': 'goals', 'value': 5}
]

goals = next((d for d in data if d['name'] == 'goals'), None)
print(goals)

no_goals = next((d for d in data if d['name'] == 'no_goals'), None)
print(no_goals)

Résultats:

goals = next((d for d in data if d['name'] == 'goals'), None)

p >


11 commentaires

En quoi est-ce «plus efficace»? C'est probablement plus lent bien que la même complexité temporelle


Pourquoi probablement plus lent?


Bien qu'il soit plus condensé, semble plus lent plutôt qu'efficace


@ juanpa.arrivillaga, Dans mes tests rapides, pour une liste de toute taille (len> 30), le générateur dans ce cas est nettement plus rapide.


Je serais curieux de voir ces tests. Que diriez-vous de len = 10 000? Si les générateurs étaient plus rapides que les anciennes boucles simples avec break , il semble que nous aurions vidé des boucles il y a longtemps.


Ouais, je ne peux pas me reproduire. Faire une boucle sur une liste est toujours (négligeable) plus rapide.


Avec l'élément recherché à la position 10000, la boucle prend presque deux fois plus de temps pour le trouver. Laissez-moi nettoyer mon code et ajouter à la publication ...


@ juanpa.arrivillaga, Moi être dans l'erreur est très certainement possible. J'utilise le code des OP ... Mais le timing est peut-être louche.


stackoverflow.com/a/48958217/6243352 propose un test de vitesse qui pourrait être pertinent. Montre LC plus rapide que gen comme plus rapide que la boucle normale. Je ne suis pas encore convaincu.


@ juanpa.arrivillaga, le timing était suspect. En utilisant timeit, le générateur semble avoir à peu près les mêmes performances pour le bouclage, mais sa configuration est plus lente. À quelque part entre 1000 et 10000 éléments, les horaires sont les mêmes. mais plus court que ça, la boucle gagne ... Merci pour les aperçus.


Merci. Mais je pensais que le générateur est connu pour être rapide en Python.



3
votes

Un dictionnaire de dictionnaires offre un temps de recherche O (1):

{'name': 'goals', 'value': 5}

Sortie:

x = [
    {'name': 'attack', 'value': 10}, 
    {'name': 'attack_side', 'value': 12},
    {'name': 'goals', 'value': 5}
]

lookup = {d['name']: d for d in x}

print(lookup['goals'])

Essayez-le!

Notes:

  • Utilisez lookup = {d ['name']: d ['value'] pour d dans x} si vous avez seulement besoin de récupérer la clé value au lieu de tout le dictionnaire.
  • Créez le dictionnaire une fois et utilisez-le pour toutes vos recherches.
  • Si vous n'effectuez qu'une seule recherche, vous disposez déjà de la solution optimale.
  • Il ne doit y avoir aucune clé name en double.


20 commentaires

@ggorlen, votre code fonctionne correctement et prend 0,04325622000033036 secondes


Je fais environ 800 recherches, car il y a environ 800 joueurs


C'est donc la voie à suivre. Construire un dictionnaire et y effectuer 800 recherches devrait vous donner un énorme gain de performances. Votre message semble indiquer que chaque joueur a une liste différente, cependant, vous devrez publier l'intégralité scénario et décrivez le nombre de recherches effectuées sur chaque sous-liste si tel est le cas.


Non, il y a environ 800 joueurs, pour chaque joueur .. Je vais chercher un dictionnaire avec 'buts' . Chaque joueur a une liste similaire à x


D'accord, cela signifie que vous ne faites qu'une seule recherche pour chaque x ? Alors ne prenez pas la peine de faire un dictionnaire.


Je pense qu'il vaut mieux dire que "chaque joueur est associé à une liste similaire à x "


Je pense que c'est probablement un problème x-y. Vous demandez comment effectuer des recherches de liste rapides, mais il semble que vous deviez peut-être reconcevoir votre application pour stocker les données dans les tables de recherche dès le début.


@AriefAnbiya faites-vous autre chose avec les données ou cherchez-vous simplement le nombre de buts pour chaque joueur?


@AriefAnbiya aussi, faites-vous cette liste de statistiques de joueurs parce que si vous l'êtes, c'est une mauvaise conception. Vous devrez peut-être reconsidérer la conception de votre application


@YangK J'ai récupéré ces données. Je ne vais pas en faire une application, uniquement à des fins d'analyse. Merci


La modification que vous avez apportée à votre message n'est pas la façon dont je voulais que cela soit utilisé. Vous ne faites qu'une seule recherche sur le dict, ce qui n'a aucun sens.


@AriefAnbiya si vous aviez gratté ces données, vous auriez dû trouver un meilleur moyen de les stocker plutôt que de mettre plusieurs dictionnaires dans une liste avec chaque liste appartenant à un joueur.


@YangK ne l'a pas dit de cette façon, c'était comme ça après avoir gratté avec Python


pouvez-vous fournir un lien vers les données récupérées pour vérifier s'il existe une meilleure façon de le faire?


@ggorlen, le playerStats [nom] ['stats'] est x . Et je suis en boucle sur tous les joueurs ( playerStats [name] est un dictionnaire {'id': ..., 'stats': x_like} )


Oui, je soutiens Yang K. Publiez le lien de données gratté et montrez-nous exactement comment vous l'utilisez. Ce que vous avez ici est très suspect.


@AriefAnbiya Merci, mais ce n'est pas ce que nous demandons. Le problème ici est que toutes vos données sont placées dans des conteneurs qui ne sont pas propices aux recherches. Si vous nous donnez votre source de données d'origine, les données brutes (API, URL, base de données, etc.), nous pouvons déterminer s'il existe un moyen de créer ces structures pour des recherches plus rapides dès le début. Une fois que les données sont dans les listes, vos mains sont liées et vous êtes coincé en boucle dessus.


L'URL est premierleague.com/players . Mais pour le moment, j'ai l'intention de connaître la meilleure façon de rechercher dans la structure actuelle.


Je pense que je sais ce que votre réponse signifie, vous voulez que le dictionnaire soit restructuré de {'name': 'buts', ...} à seulement {'buts': valeur} < / code> pour faciliter l'accès aux valeurs


continuons cette discussion dans le chat .



0
votes

Je suggère une approche différente: convertir la liste de dictionnaires dans un format différent, précisément dans un dict:

for ability in player_x.keys():
  print(ability, player_x[ability])

# attack 10
# attack_side 12
# goals 5

Ensuite, il est facile d'obtenir:

print(player_x.get('attack', None)) #=> 10
print(player_x.get('whathever', None)) #=> None

Ou aussi:

x = [{'name': 'attack', 'value': 10}, {'name': 'attack_side', 'value': 12},{'name': 'goals', 'value': 5}]

player_x = { ability['name']: ability['value'] for ability in x }
#=> {'attack': 10, 'attack_side': 12, 'goals': 5}


0 commentaires