You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键说明

  1. 正则转义:用re.escape()处理玩家名,避免像Bob T.里的.被正则当成通配符,导致匹配错误。
  2. f-string拼接:用fr""构造原始字符串(避免转义字符冲突),把变量直接插入正则模式中。
  3. 匹配逻辑:模式"{player} @ .*{action}"完全对应日志格式,确保只统计目标玩家的指定操作。

内容的提问来源于stack exchange,提问作者pnat_1040

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 11:47:43