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

如何用Python列表推导式创建多副扑克牌的合并扁平列表?

问题描述

我定义了如下Card类:

class Card:
    def __init__(self, rank, suit, d=0): 
        self.rank = rank
        self.suit = suit
        self.deck_index = d

通过列表推导式可以生成单副标准扑克牌的Card对象列表:

ranks = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
suits = ['hearts', 'clubs', 'diamonds', 'spades']
deck = ([Card(r, s) for r in ranks for s in suits] + 
        [Card('Joker', 'black'), Card('Joker', 'red')])

现在需要用列表推导式生成N副合并后的扁平Card对象列表。用for循环可以实现需求:

decks = []
for i in range(N):
    decks += ([Card(r, s, d=i) for r in ranks for s in suits] +
              [Card('Joker', 'black', i), Card('Joker', 'red', i)])

但直接转成列表推导式会得到嵌套列表(列表的列表),而非扁平的Card对象列表:

decks = [[Card(r, s, d=i) for r in ranks for s in suits] + 
         [Card('Joker', 'black', i), Card('Joker', 'red', i)] 
         for i in range(N)]

尝试用*解包会触发错误:Iterable unpacking cannot be used in comprehension。

如果分开推导普通牌组和大小王再合并,不仅会重复循环,还无法保留每副牌自带大小王的顺序:

decks = ([Card(r, s, i) for r in ranks for s in suits for i in range(N)] + 
         [Card('Joker', 'black', i) for i in range(N)] + 
         [Card('Joker', 'red', i) for i in range(N)])

通用问题

已知lst = lst1 + lst2是元素列表,lsts = [lst1(i) + lst2(i) for i in range(N)]是嵌套列表,如何用列表推导式直接生成包含所有lst1(i) + lst2(i)元素的扁平列表?(不想先生成嵌套列表再做扁平化处理)


解决方案

方法1:嵌套循环的列表推导式(直接生成扁平列表)

在列表推导式中通过多层循环,直接遍历每个牌组的所有元素,避免生成中间嵌套列表:

decks = [
    card
    for i in range(N)
    for card in ([Card(r, s, d=i) for r in ranks for s in suits] + [Card('Joker', 'black', i), Card('Joker', 'red', i)])
]

如果想要更清晰的层级,可以拆分普通牌和大小王的遍历逻辑:

decks = [
    card
    for i in range(N)
    # 遍历当前副牌的所有普通牌
    for r in ranks
    for s in suits
    for card in [Card(r, s, d=i)]
    # 遍历当前副牌的大小王
    for card in [Card('Joker', 'black', i), Card('Joker', 'red', i)]
]

方法2:借助itertools.chain实现扁平化

使用itertools.chain.from_iterable直接拼接每个牌组的元素序列,无需生成嵌套列表:

from itertools import chain

decks = list(chain.from_iterable(
    ([Card(r, s, d=i) for r in ranks for s in suits] + [Card('Joker', 'black', i), Card('Joker', 'red', i)])
    for i in range(N)
))

如果想减少内存开销,可以用生成器表达式替代内层列表推导式:

from itertools import chain

def generate_single_deck(deck_idx):
    # 生成普通牌
    for rank in ranks:
        for suit in suits:
            yield Card(rank, suit, d=deck_idx)
    # 生成大小王
    yield Card('Joker', 'black', deck_idx)
    yield Card('Joker', 'red', deck_idx)

decks = list(chain.from_iterable(generate_single_deck(i) for i in range(N)))

方法3:合并元素生成逻辑到同一层级

把每个牌组的普通牌和大小王合并到同一个推导循环里,通过预先构造元素元组保证顺序:

decks = [
    Card(rank, suit, d=i)
    for i in range(N)
    for rank, suit in [(r, s) for r in ranks for s in suits] + [('Joker', 'black'), ('Joker', 'red')]
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 17:37:33