2017-11-26 16 views
8

Trong Python 3.6.3 Có cách nào lặp lại dù một danh sách này sang danh sách khác không?Làm thế nào để lặp qua nhiều danh sách tuần tự với một vòng lặp?

Ví dụ:

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

(Trong trường hợp này, tôi muốn lặp qua các thẻ phải đối mặt ngay sau khi thẻ không trực tiếp.)

Để làm rõ: Dòng trên ném một:

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

Đây là vấn đề của tôi.

+0

Ví dụ của bạn không rõ ràng. Kết quả/đầu ra mong đợi là gì? – timgeb

+0

@timgeb Trong ví dụ này, tôi đang cố gắng tạo một bộ bài 52 tiêu chuẩn. Vấn đề là tôi muốn lặp lại thông qua {"J", "Q", "K", "A"} ngay sau thẻ được đánh số mà không cần vòng lặp thứ hai. – Josh

+0

@schwobaseggl Dòng này ném một lỗi kiểu: "TypeError: loại toán hạng không được hỗ trợ (s) cho +: 'phạm vi' và 'danh sách'" – Josh

Trả lời

17

range không trả lại list bằng Python3, vì vậy range(2, 10) + ["J", "Q", "K", "A"] không hoạt động, nhưng list(range(2, 10)) + ["J", "Q", "K", "A"] thì có. Bạn cũng có thể sử dụng itertools.chain để nối 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" 
] 

Các hiểu lồng nhau không, tất nhiên, tạo thành một sản phẩm Descartes mà bạn cũng có thể sử dụng một util cho:

from itertools import product 
deck = list(product(chain(range(2, 10), "JQKA"), "HCDS")) 
8

Vấn đề với mã hiện tại của bạn là ở đây:

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

Trước hết, nó phải là range(2, 11), nếu không, thẻ với số lượng 10 được bỏ qua. Thứ hai, để tham gia phạm vi và danh sách, bạn sẽ phải làm như vậy:

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

Vì vậy, kết quả cuối cùng sẽ là:

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

Tôi nghĩ rằng đây sẽ cung cấp cho bạn mong muốn đầu ra (đầu tiên tất cả các thẻ không phải đối mặt, sau đó tất cả các thẻ mặt).

+1

Điều này sẽ hiệu quả, nhưng @schwobaseggl có giải pháp tốt hơn bằng cách sử dụng itertools, vì nó không yêu cầu xây dựng danh sách không cần thiết, và sau đó liệt kê nối. –

3

Trong Python3, bạn có thể sử dụng giải nén: giải pháp

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

Không cần gọi 'list' ở đó:' [* phạm vi (2, 10), "J", "Q", "K", "A"] 'là đủ. (Hoặc thậm chí '[* phạm vi (2, 11), *" JQKA "]'.) –

+0

@MarkDickinson tốt để biết. Vui lòng xem chỉnh sửa gần đây của tôi. – Ajax1234

5

Xem @ schwobaseggl cho những gì bạn muốn, nhưng tôi thường thích để đại diện cho thẻ như là một chuỗi 2 nhân vật, tuy nhiên:

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

Điều này dễ đọc hơn theo ý kiến ​​của tôi và sẽ vẫn hoạt động giống như một bộ xếp hạng, phù hợp.

+0

Không cần '*' – schwobaseggl

2

chỉ tập trung vào các lỗi bạn nhận được:

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

tôi sẽ cung cấp cho bạn một lời giải thích.

mã hiện tại của bạn không làm việc trong Python 2:

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

sẽ in:

[(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')] 

Trong Python 3 bạn phải sử dụng 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) 

sẽ pr int:

[(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')] 

Bạn phải sử dụng list()range() bằng Python 3 không tạo ra một loại chuỗi bất biến, không phải là một danh sách.

Các vấn đề liên quan