Python中遍历列表结合str.contains统计扑克玩家操作次数问题
解决扑克操作统计的正则匹配问题
你遇到的问题根源是正则表达式里没有正确插入变量——你写的'(player).*(action)'是字面量字符串,Python不会把player和action变量的值替换进去,所以实际在匹配包含"player"和"action"这两个单词的日志,自然统计结果全是0。
第一步:修正单个操作的统计函数
我们需要用f-string拼接正则模式,同时用re.escape()处理玩家名里的特殊字符(比如Bob T.里的.,在正则里是通配符,需要转义),确保匹配准确:
import re import pandas as pd # 构造样本DataFrame(基于你提供的entry数据) entry_data = [ "-- ending hand #174 --", "\"Prof @ ZY_G_5ZOve\" gained 100", "\"tom_thumb @ g1PBaozt7k\" folds", "\"Prof @ ZY_G_5ZOve\" calls with 50", "\"tom_thumb @ g1PBaozt7k\" checks", "river: 9♦, 5♣, Q♥, 7♠ [K♠]", "\"Prof @ ZY_G_5ZOve\" checks", "\"tom_thumb @ g1PBaozt7k\" checks", "turn: 9♦, 5♣, Q♥ [7♠]", "\"Prof @ ZY_G_5ZOve\" checks", "\"tom_thumb @ g1PBaozt7k\" checks", "flop: [9♦, 5♣, Q♥]", "\"Prof @ ZY_G_5ZOve\" checks", "\"tom_thumb @ g1PBaozt7k\" calls with 50", "\"Bob T. @ fjZTXUGV2G\" folds", "\"danny G @ tNE1_lEFYv\" folds", "\"Prof @ ZY_G_5ZOve\" posts a big blind of 50", "\"tom_thumb @ g1PBaozt7k\" posts a small blind of 25", "-- starting hand #174 (Texas Hold'em) (dealer: \"Bob T. @ fjZTXUGV2G\") --", "-- ending hand #173 --", "\"tom_thumb @ g1PBaozt7k\" gained 475", "\"danny G @ tNE1_lEFYv\" folds", "\"Prof @ ZY_G_5ZOve\" folds", "\"tom_thumb @ g1PBaozt7k\" raises with 356", "flop: [4♥, A♠, 6♠]", "\"danny G @ tNE1_lEFYv\" calls with 150", "\"Prof @ ZY_G_5ZOve\" calls with 150", "\"tom_thumb @ g1PBaozt7k\" raises with 150", "\"Bob T. @ fjZTXUGV2G\" folds", "\"danny G @ tNE1_lEFYv\" calls with 50", "\"Prof @ ZY_G_5ZOve\" calls with 50", "\"tom_thumb @ g1PBaozt7k\" posts a big blind of 50", "\"Bob T. @ fjZTXUGV2G\" posts a small blind of 25", "-- starting hand #173 (Texas Hold'em) (dealer: \"danny G @ tNE1_lEFYv\") --" ] df = pd.DataFrame({'entry': entry_data}) player_list = ['danny G', 'Jane', 'Prof', 'spn', 'tim', 'Bob T.', 'joon', 'tom_thumb'] action_list = ['call', 'fold'] def action_amount(df, player_list, action): for player in player_list: # 转义玩家名特殊字符,构造精准正则模式 pattern = fr'"{re.escape(player)} @ .*{action}' # 统计匹配的日志行数 action_number = len(df[df['entry'].str.contains(pattern, regex=True)]) print(f'{player} {action}ed {action_number} times.') # 测试单个操作统计 action_amount(df, player_list, 'call')
运行这段代码,就能得到你预期的输出:
danny G called 2 times. Jane called 0 times. Prof called 3 times. spn called 0 times. tim called 0 times. Bob T. called 0 times. joon called 0 times. tom_thumb called 1 times.
第二步:优化为同时遍历玩家和操作列表
如果要一次性统计所有玩家的所有操作,可以修改函数,生成更结构化的统计结果(比如返回DataFrame):
def all_action_stats(df, player_list, action_list): # 初始化统计字典 stats = {player: {action:0 for action in action_list} for player in player_list} for player in player_list: player_escaped = re.escape(player) for action in action_list: pattern = fr'"{player_escaped} @ .*{action}' stats[player][action] = len(df[df['entry'].str.contains(pattern, regex=True)]) # 转换为DataFrame方便查看和后续处理 stats_df = pd.DataFrame.from_dict(stats, orient='index') return stats_df # 生成全量统计结果 result_df = all_action_stats(df, player_list, action_list) print(result_df)
输出结果:
call fold danny G 2 2 Jane 0 0 Prof 3 1 spn 0 0 tim 0 0 Bob T. 0 2 joon 0 0 tom_thumb 1 1
关键说明
- 正则转义:用
re.escape()处理玩家名,避免像Bob T.里的.被正则当成通配符,导致匹配错误。 - f-string拼接:用
fr""构造原始字符串(避免转义字符冲突),把变量直接插入正则模式中。 - 匹配逻辑:模式
"{player} @ .*{action}"完全对应日志格式,确保只统计目标玩家的指定操作。
内容的提问来源于stack exchange,提问作者pnat_1040
相关产品推荐
相关产品推荐

