如何按多列自定义排序存储MTG卡牌的DataFrame?
万智牌DataFrame按官方套牌规则排序解决方案
核心需求回顾
- 颜色排序优先级:W → U → B → R → G → 多色 → 无色(非地牌) → 地牌
- 同优先级组内按卡牌名称字母序排序
原代码问题分析
- 地牌判断函数错误:
card_type.contains应为字符串方法str.contains,且返回值逻辑颠倒——要让地牌排最后,需给地牌分配更大的排序值 sort_values参数用法错误:key列表需与by列一一对应,不能直接传入列对象;名称排序无需额外处理,直接用默认字母序即可- 无色组未拆分:原逻辑未区分无色非地牌和地牌,导致地牌无法单独排到最后
修正后的完整代码
def get_color_order(color): # 适配Colors列为字符串格式(如"['W']")的情况 color_order = { "['W']": 1, "['U']": 2, "['B']": 3, "['R']": 4, "['G']": 5, "[]": 7, # 无色非地牌的优先级 } # 多色卡牌返回6,排在无色非地牌之前 return color_order.get(color, 6) def get_land_priority(card_type): # 非地牌返回0,地牌返回1,确保地牌在同颜色组内排最后 return 1 if "Land" in card_type else 0 # 执行排序 filtered_df = filtered_df.sort_values( by=["Colors", "Type", "Name"], key=[ lambda x: x.apply(get_color_order), lambda x: x.apply(get_land_priority), lambda x: x.str.lower() # 可选:不区分大小写排序,去掉则按原大小写排序 ] )
代码说明
- 颜色排序:保持单颜色1-5的优先级,多色返回6,无色非地牌返回7,完全匹配官方规则顺序
- 地牌优先级处理:通过
get_land_priority给地牌标记更高的数值,在同一颜色组(尤其是无色组)里,非地牌会优先排序 - 名称排序:用
str.lower()实现不区分大小写的字母序排序,若需要严格区分大小写可移除该lambda
适配列表类型Colors列
如果你的Colors列存储的是实际列表(如['W']、['U','B'])而非字符串,可替换颜色排序函数为:
def get_color_order(color_list): if not color_list: return 7 # 无色非地牌 elif len(color_list) == 1: # 单颜色优先级映射 color_map = {'W':1, 'U':2, 'B':3, 'R':4, 'G':5} return color_map.get(color_list[0], 6) else: return 6 # 多色卡牌
内容的提问来源于stack exchange,提问作者The CodeWriter
相关产品推荐
相关产品推荐

