How to loop through multiple lists sequentially wi

2020-03-15 07:06发布

In Python 3.6.3 Is there a way to loop though one list after another?

For example:

deck = [(value, suit) for value in range(2, 11) +
            ["J", "Q", "K", "A"] for suit in ["H", "C", "D", "S"]]

(In this case, I want to loop through the face cards right after the non-face cards.)

For clarification: The above line throws a:

TypeError: unsupported operand type(s) for +: 'range' and 'list'

This is my problem.

5条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-03-15 07:36

range doesn't return a list in Python3, so range(2, 10) + ["J", "Q", "K", "A"] doesn't work, but list(range(2, 10)) + ["J", "Q", "K", "A"] does. You can also use itertools.chain to concatenate iterables:

from itertools import chain 

chain(range(2, 10), ["J", "Q", "K", "A"])
# or even shorter:
chain(range(2, 10), "JQKA")  # as strings themselves are iterables

# so this comprehension will work
deck = [
   (value, suit) 
   for value in chain(range(2, 10), "JQKA") 
   for suit in "HCDS"
]

The nested comprehension does, of course, constitute a cartesian product which you can also use a util for:

from itertools import product
deck = list(product(chain(range(2, 10), "JQKA"), "HCDS"))
查看更多
倾城 Initia
3楼-- · 2020-03-15 07:46

In Python3, you can use unpacking:

deck = [(value, suit) for value in [*range(2, 10), "J", "Q", "K", "A"] for suit in ["H", "C", "D", "S"]]
查看更多
ゆ 、 Hurt°
4楼-- · 2020-03-15 07:51

See @schwobaseggl's solution for what you want, but I usually prefer to represent cards as a 2 character string, however:

deck = [r+s for r in '23456789TJQKA' for s in 'hcds']

This is more readable in my opinion, and will still behave a lot like a tuple of rank, suit.

查看更多
虎瘦雄心在
5楼-- · 2020-03-15 07:51

Focusing only in the error you do get:

TypeError: unsupported operand type(s) for +: 'range' and 'list

I will give you an explanation.

Your current code does work in Python 2:

deck = [(value, suit) for value in range(2, 11) + ["J", "Q", "K", "A"] for suit in ["H", "C", "D", "S"]]
print deck

will print:

[(2, 'H'), (2, 'C'), (2, 'D'), (2, 'S'), (3, 'H'), (3, 'C'), (3, 'D'), (3, 'S'), (4, 'H'), (4, 'C'), (4, 'D'), (4, 'S'), (5, 'H'), (5, 'C'), (5, 'D'), (5, 'S'), (6, 'H'), (6, 'C'), (6, 'D'), (6, 'S'), (7, 'H'), (7, 'C'), (7, 'D'), (7, 'S'), (8, 'H'), (8, 'C'), (8, 'D'), (8, 'S'), (9, 'H'), (9, 'C'), (9, 'D'), (9, 'S'), (10, 'H'), (10, 'C'), (10, 'D'), (10, 'S'), ('J', 'H'), ('J', 'C'), ('J', 'D'), ('J', 'S'), ('Q', 'H'), ('Q', 'C'), ('Q', 'D'), ('Q', 'S'), ('K', 'H'), ('K', 'C'), ('K', 'D'), ('K', 'S'), ('A', 'H'), ('A', 'C'), ('A', 'D'), ('A', 'S')]

In Python 3 you have to use list(range(2, 11)):

deck = [(value, suit) for value in list(range(2, 11)) + ["J", "Q", "K", "A"] for suit in ["H", "C", "D", "S"]]
print(deck)

will print:

[(2, 'H'), (2, 'C'), (2, 'D'), (2, 'S'), (3, 'H'), (3, 'C'), (3, 'D'), (3, 'S'), (4, 'H'), (4, 'C'), (4, 'D'), (4, 'S'), (5, 'H'), (5, 'C'), (5, 'D'), (5, 'S'), (6, 'H'), (6, 'C'), (6, 'D'), (6, 'S'), (7, 'H'), (7, 'C'), (7, 'D'), (7, 'S'), (8, 'H'), (8, 'C'), (8, 'D'), (8, 'S'), (9, 'H'), (9, 'C'), (9, 'D'), (9, 'S'), (10, 'H'), (10, 'C'), (10, 'D'), (10, 'S'), ('J', 'H'), ('J', 'C'), ('J', 'D'), ('J', 'S'), ('Q', 'H'), ('Q', 'C'), ('Q', 'D'), ('Q', 'S'), ('K', 'H'), ('K', 'C'), ('K', 'D'), ('K', 'S'), ('A', 'H'), ('A', 'C'), ('A', 'D'), ('A', 'S')]

You have to use list() because range() in Python 3 does create an immutable sequence type, not a list.

查看更多
相关推荐>>
6楼-- · 2020-03-15 07:57

The problem with your current code is here:

range(2, 10) + ["J", "Q", "K", "A"]

First off, it should be range(2, 11), otherwise, cards with the number 10 are omitted. Second, in order to join the range and the list, you'll have to do like so:

list(range(2, 11)) + ["J", "Q", "K", "A"]

So the final result will be:

deck = [(value, suit) for value in list(range(2, 11)) + ["J", "Q", "K", "A"] for suit in ["H", "C", "D", "S"]]

I think this will give you the desired output (first all non-face cards, then all face cards).

查看更多
登录 后发表回答