如何与 Python 中的字符串进行交叉乘法?

How can I do cross multiplication with strings in Python?

我有两个字符串列表,它们是:

Deck13Sample = [
    'Two', 'Three', 'Four', 'Five', 'Six', 'Seven',
    'Eight', 'Nine', 'Ten', 'Jack', 'Queen', 'King', 'Ace'
]
CardTypes = [' of Hearts', ' of Spades', ' of Diamonds', ' of Clubs']

我想将列表相乘,得到一个完整的套牌,看起来像

Deck52Sample = ['Two of Hearts', 'Three of Hearts', 'Four of Hearts', ...]

因为Python不能内建字符串交叉相乘,所以我完全不知道我现在应该做什么。

将其中一个转换为 2D 字符数组,然后使用 np.char.add to join them in a broadcasted-way -

In [18]: np.char.add(Deck13Sample,np.array(CardTypes)[:,None])
Out[18]: 
array([['Two of Hearts', 'Three of Hearts', 'Four of Hearts',
        'Five of Hearts', 'Six of Hearts', 'Seven of Hearts',
        'Eight of Hearts', 'Nine of Hearts', 'Ten of Hearts',
        'Jack of Hearts', 'Queen of Hearts', 'King of Hearts',
        'Ace of Hearts'],
       ['Two of Spades', 'Three of Spades', 'Four of Spades',
        'Five of Spades', 'Six of Spades', 'Seven of Spades',
        'Eight of Spades', 'Nine of Spades', 'Ten of Spades',
        'Jack of Spades', 'Queen of Spades', 'King of Spades',
        'Ace of Spades'],
       ['Two of Diamonds', 'Three of Diamonds', 'Four of Diamonds',
        'Five of Diamonds', 'Six of Diamonds', 'Seven of Diamonds',
        'Eight of Diamonds', 'Nine of Diamonds', 'Ten of Diamonds',
        'Jack of Diamonds', 'Queen of Diamonds', 'King of Diamonds',
        'Ace of Diamonds'],
       ['Two of Clubs', 'Three of Clubs', 'Four of Clubs',
        'Five of Clubs', 'Six of Clubs', 'Seven of Clubs',
        'Eight of Clubs', 'Nine of Clubs', 'Ten of Clubs',
        'Jack of Clubs', 'Queen of Clubs', 'King of Clubs',
        'Ace of Clubs']], dtype='<U17')

使用itertools.product

>>> from itertools import product as pd

>>> Deck13Sample = ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King','Ace']
>>> CardTypes = [' of Hearts',' of Spades',' of Diamonds',' of Clubs']

>>> [ i+j for i, j in pd(Deck13Sample, CardTypes)]
['Two of Hearts', 'Two of Spades', 'Two of Diamonds', 'Two of Clubs', 'Three of Hearts', 'Three of Spades', 'Three of Diamonds', 'Three of Clubs', 'Four of Hearts', 'Four of Spades', 'Four of Diamonds', 'Four of Clubs', 'Five of Hearts', 'Five of Spades', 'Five of Diamonds', 'Five of Clubs', 'Six of Hearts', 'Six of Spades', 'Six of Diamonds', 'Six of Clubs', 'Seven of Hearts', 'Seven of Spades', 'Seven of Diamonds', 'Seven of Clubs', 'Eight of Hearts', 'Eight of Spades', 'Eight of Diamonds', 'Eight of Clubs', 'Nine of Hearts', 'Nine of Spades', 'Nine of Diamonds', 'Nine of Clubs', 'Ten of Hearts', 'Ten of Spades', 'Ten of Diamonds', 'Ten of Clubs', 'Jack of Hearts', 'Jack of Spades', 'Jack of Diamonds', 'Jack of Clubs', 'Queen of Hearts', 'Queen of Spades', 'Queen of Diamonds', 'Queen of Clubs', 'King of Hearts', 'King of Spades', 'King of Diamonds', 'King of Clubs', 'Ace of Hearts', 'Ace of Spades', 'Ace of Diamonds', 'Ace of Clubs']

一种方法是使用 itertools.product、列表理解和使用 + 运算符的字符串连接:

import itertools

deck = [rank + suit for rank, suit in itertools.product(Deck13Sample, CardTypes)]

结果:

In [28]: deck
Out[28]: 
['Two of Hearts',
 'Two of Spades',
 'Two of Diamonds',
...
'Ace of Spades',
'Ace of Diamonds',
'Ace of Clubs']

您可以使用嵌套的 for 循环:

Deck52Sample = []
for number in Deck13Sample:
    for suit in CardTypes:
        Deck52Sample.append(number + suit)

我想到了原版 Python 中的三个选项。对于所有这些选项,您真的不需要在套装名称前加上 ' of '。我将使用 CardTypes = ['Hearts', 'Spades', 'Diamonds', 'Clubs'].

的含义
  1. 使用嵌套的 for 循环。毕竟,这就是叉积:

    deck = []
    for rank in Deck13Sample:
        for suit in CardTypes:
            deck.append(f'{rank} of {suit}')
    
  2. 同样的事情可以用列表理解来表达得更简洁。这是我推荐的选项:

    deck = [f'{rank} of {suit}' for rank in Deck13Sample for suit in CardTypes]
    

    注意循环的顺序与#1 相同。

  3. 最后,如果你想使用花哨的库导入(但是Python自带的),你可以使用itertools.product,它基本上是一个无限嵌套的集合for 循环,因此对于这个问题来说有点矫枉过正:

    deck = [f'{rank} of {suit}' for rank, suit in itertools.product(Deck13Sample, CardTypes)]
    

供参考,一副牌上的数字称为 "rank",符号称为 "suit"。

对于对象 dtype 字符串,广播的解决方案可以使用加法(字符串连接):

In [45]: Deck13Sample = ['Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten','Jack','Queen','King'
    ...: ,'Ace'] 
    ...: CardTypes = [' of Hearts',' of Spades',' of Diamonds',' of Clubs']                                  
In [46]: A=np.array(Deck13Sample,object)                                                                     
In [47]: B=np.array(CardTypes,object)                                                                        
In [48]: A[None,:]+B[:,None]                                                                                 
Out[48]: 
array([['Two of Hearts', 'Three of Hearts', 'Four of Hearts',
        'Five of Hearts', 'Six of Hearts', 'Seven of Hearts',
        'Eight of Hearts', 'Nine of Hearts', 'Ten of Hearts',
        'Jack of Hearts', 'Queen of Hearts', 'King of Hearts',
        'Ace of Hearts'],
       ['Two of Spades', 'Three of Spades', 'Four of Spades',
        'Five of Spades', 'Six of Spades', 'Seven of Spades',
        'Eight of Spades', 'Nine of Spades', 'Ten of Spades',
        'Jack of Spades', 'Queen of Spades', 'King of Spades',
        'Ace of Spades'],
       ['Two of Diamonds', 'Three of Diamonds', 'Four of Diamonds',
        'Five of Diamonds', 'Six of Diamonds', 'Seven of Diamonds',
        'Eight of Diamonds', 'Nine of Diamonds', 'Ten of Diamonds',
        'Jack of Diamonds', 'Queen of Diamonds', 'King of Diamonds',
        'Ace of Diamonds'],
       ['Two of Clubs', 'Three of Clubs', 'Four of Clubs',
        'Five of Clubs', 'Six of Clubs', 'Seven of Clubs',
        'Eight of Clubs', 'Nine of Clubs', 'Ten of Clubs',
        'Jack of Clubs', 'Queen of Clubs', 'King of Clubs',
        'Ace of Clubs']], dtype=object)

但我认为列表理解版本没有任何问题。我们只生成 52 个项目。考虑到数组的转换,列表版本可能同样快,甚至更快。

In [54]: timeit [[i+j for j in CardTypes] for i in Deck13Sample]                                             
10.3 µs ± 262 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [55]: timeit np.array(Deck13Sample,object)[None,:]+np.array(CardTypes,object)[:,None]                     
21.5 µs ± 37.2 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [56]: timeit np.char.add(Deck13Sample,np.array(CardTypes)[:,None])                                        
65.7 µs ± 1.72 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)