2

I have two lists of strings which are:

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

I want to multiply the lists, to get a complete deck which would look like

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

Since Python can not cross-multiply strings built-in, I am totally clueless of what I should do now.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Yekta Aktaş
  • 125
  • 1
  • 9

6 Answers6

4

Convert one of those to a 2D char array and then use 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')
Divakar
  • 218,885
  • 19
  • 262
  • 358
4

Use 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']
Vicrobot
  • 3,795
  • 1
  • 17
  • 31
2

you could use a nested for loop:

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

Three options in vanilla Python that come to mind. For all these options, you really don't need to prepend ' of ' to the suit name. I will work with the implication that CardTypes = ['Hearts', 'Spades', 'Diamonds', 'Clubs'].

  1. Use a nested for loop. After all, that's what a cross product is:

    deck = []
    for rank in Deck13Sample:
        for suit in CardTypes:
            deck.append(f'{rank} of {suit}')
    
  2. The same thing can be expressed much more concisely as a list comprehension. This is the option I would recommend:

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

    Notice that the order of the loops is the same as in #1.

  3. Finally, if you want to use a fancy library import (but one that comes with Python), you can use itertools.product, which is basically an indefinitely nested set of for loops, and therefore overkill for this problem:

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

For reference, the numbers are called "rank" and the symbols are called "suit" on a deck of cards.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
1

One way would be using itertools.product, a list comprehension, and string concatenation using the + operator:

import itertools

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

Results:

In [28]: deck
Out[28]: 
['Two of Hearts',
 'Two of Spades',
 'Two of Diamonds',
...
'Ace of Spades',
'Ace of Diamonds',
'Ace of Clubs']
sjw
  • 6,213
  • 2
  • 24
  • 39
1

With object dtype strings the broadcasted solution can use addition (string join):

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)

But I don't think there's anything wrong with the list comprehension versions. We are only generating 52 items. Taking the conversion to array into account the list versions are probably just as fast, if not faster.

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)
hpaulj
  • 221,503
  • 14
  • 230
  • 353