Chuyển đổi tuple sang danh sách và quay lại


206

Tôi hiện đang làm việc trên một trình chỉnh sửa bản đồ cho một trò chơi trong pygame, sử dụng bản đồ ô vuông. Mức được xây dựng từ các khối trong cấu trúc sau (mặc dù lớn hơn nhiều):

level1 = (
         (1,1,1,1,1,1)
         (1,0,0,0,0,1)
         (1,0,0,0,0,1)
         (1,0,0,0,0,1)
         (1,0,0,0,0,1)
         (1,1,1,1,1,1))

trong đó "1" là một khối là một bức tường và "0" là một khối không khí trống rỗng.

Mã sau đây về cơ bản là mã xử lý thay đổi loại khối:

clicked = pygame.mouse.get_pressed()
if clicked[0] == 1:
    currLevel[((mousey+cameraY)/60)][((mousex+cameraX)/60)] = 1

Nhưng vì mức được lưu trữ trong một tuple, tôi không thể thay đổi giá trị của các khối khác nhau. Làm thế nào để tôi thay đổi các giá trị khác nhau ở cấp độ một cách dễ dàng?


12
không sử dụng một tuple, chỉ sử dụng một danh sách từ đầu. Nó thực sự có thể làm chậm mã của bạn nếu cấp độ của bạn rất lớn, nếu bạn phải tiếp tục chuyển đổi chúng
jamylak

4
Làm thế nào về việc đi với danh sách thay vì bộ dữ liệu ngay từ đầu?
Krzysztof Bujniewicz

4
@ user2133308 btw chỉ là một ghi chú tương thích, bạn nên sử dụng phép chia số nguyên //thay vì chỉ /vì trong Python 3, /sẽ thực hiện phân chia dấu phẩy động và làm hỏng mã của bạn.
jamylak

Câu trả lời:


284

Chuyển đổi tuple sang danh sách:

>>> t = ('my', 'name', 'is', 'mr', 'tuple')
>>> t
('my', 'name', 'is', 'mr', 'tuple')
>>> list(t)
['my', 'name', 'is', 'mr', 'tuple']

Chuyển đổi danh sách sang tuple:

>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')

5
Điều này không làm việc cho tôi. Nếu tôi chạy mã trong khối đầu tiên để chuyển đổi tuple t thành danh sách bằng cách chuyển t sang list (), tôi nhận được thông báo lỗi: "*** Lỗi trong đối số: '(t)'" Điều này dường như xảy ra với tôi chỉ trong khi gỡ lỗi. Vẫn bối rối.
Jimmy

4
@Jimmy đó là vì danh sách là lệnh gỡ lỗi, p list(...)thay vào đó hãy chạy .
moritz

74

Bạn có một tuple tuple.
Để chuyển đổi mọi tuple thành một danh sách:

[list(i) for i in level] # list of lists

--- HOẶC LÀ ---

map(list, level)

Và sau khi bạn chỉnh sửa xong, chỉ cần chuyển đổi chúng trở lại:

tuple(tuple(i) for i in edited) # tuple of tuples

--- HOẶC --- (Cảm ơn @jamylak)

tuple(itertools.imap(tuple, edited))

Bạn cũng có thể sử dụng một mảng numpy:

>>> a = numpy.array(level1)
>>> a
array([[1, 1, 1, 1, 1, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 1],
       [1, 1, 1, 1, 1, 1]])

Để thao tác:

if clicked[0] == 1:
    x = (mousey + cameraY) // 60 # For readability
    y = (mousex + cameraX) // 60 # For readability
    a[x][y] = 1

2
NumPy là gói cơ bản cho tính toán khoa học với Python. Đối tượng chính của NumPy là mảng đa chiều đồng nhất. Đó là một bảng các phần tử (thường là số), tất cả cùng loại, được lập chỉ mục bởi một bộ số nguyên dương.
pradyunsg 4/12/2016

24

Bạn có thể có một danh sách các danh sách. Chuyển đổi bộ dữ liệu của bạn thành một danh sách các danh sách bằng cách sử dụng:

level1 = [list(row) for row in level1]

hoặc là

level1 = map(list, level1)

và sửa đổi chúng cho phù hợp.

Nhưng một mảng numpy là mát mẻ.


18

Để chuyển đổi bộ dữ liệu sang danh sách

(Dấu phẩy bị thiếu giữa các bộ dữ liệu trong câu hỏi đã cho, nó được thêm vào để ngăn thông báo lỗi)

Cách 1:

level1 = (
     (1,1,1,1,1,1),
     (1,0,0,0,0,1),
     (1,0,0,0,0,1),
     (1,0,0,0,0,1),
     (1,0,0,0,0,1),
     (1,1,1,1,1,1))

level1 = [list(row) for row in level1]

print(level1)

Cách 2:

level1 = map(list,level1)

print(list(level1))

Phương pháp 1 mất --- 0,0019991397857666016 giây ---

Phương pháp 2 mất --- 0,0010001659393310547 giây ---


14

Tại sao bạn không thử chuyển đổi loại từ một tuple sang danh sách và ngược lại.

level1 = (
     (1,1,1,1,1,1)
     (1,0,0,0,0,1)
     (1,0,0,0,0,1)
     (1,0,0,0,0,1)
     (1,0,0,0,0,1)
     (1,1,1,1,1,1))

print(level1)

level1 = list(level1)

print(level1)

level1 = tuple(level1)

print(level1)

5

Cả hai câu trả lời đều tốt, nhưng một lời khuyên nhỏ:

Tuples là bất biến, ngụ ý rằng chúng không thể thay đổi. Vì vậy, nếu bạn cần thao tác dữ liệu, tốt hơn là lưu trữ dữ liệu trong một danh sách, nó sẽ giảm chi phí không cần thiết.

Trong trường hợp của bạn, trích xuất dữ liệu vào một danh sách, như được hiển thị bởi eumiro, và sau khi sửa đổi, tạo ra một bộ cấu trúc tương tự như câu trả lời được đưa ra bởi Schoolboy.

Ngoài ra, như được đề xuất sử dụng mảng numpy là một lựa chọn tốt hơn


Bạn cũng nên viết trong câu trả lời này, điều đó numpysẽ cung cấp giải pháp nhanh nhất để làm việc với loại dữ liệu này.
jamylak

Tất nhiên bạn có thể sử dụng các cấu trúc dữ liệu bất biến như bộ dữ liệu ngay cả khi bạn đang thao tác dữ liệu. Toàn bộ tiền đề của lập trình chức năng và tất cả những gì chủ yếu dựa trên sự kiên trì của dữ liệu. Nhưng tất nhiên, ở vùng đất Python bạn có thể muốn đi cùng với quần chúng và biến đổi tự do ...
nperson325681

5

Danh sách Tuple và trở lại có thể được thực hiện như dưới đây

import ast, sys
input_str = sys.stdin.read()
input_tuple = ast.literal_eval(input_str)

l = list(input_tuple)
l.append('Python')
#print(l)
tuple_2 = tuple(l)

# Make sure to name the final tuple 'tuple_2'
print(tuple_2)

2

Bạn có thể tăng tốc đáng kể công cụ của mình nếu bạn chỉ sử dụng một danh sách thay vì danh sách danh sách. Tất nhiên điều này chỉ có thể nếu tất cả các danh sách bên trong của bạn có cùng kích thước (điều này đúng trong ví dụ của bạn, vì vậy tôi chỉ giả sử điều này).

WIDTH = 6
level1 = [ 1,1,1,1,1,1,
           1,0,0,0,0,1,
           1,0,0,0,0,1,
           1,0,0,0,0,1,
           1,0,0,0,0,1,
           1,1,1,1,1,1 ]
print level1[x + y*WIDTH]  # print value at (x,y)

Và bạn thậm chí có thể nhanh hơn nếu bạn sử dụng bitfield thay vì danh sách:

WIDTH = 8  # better align your width to bytes, eases things later
level1 = 0xFC84848484FC  # bit field representation of the level
print "1" if level1 & mask(x, y) else "0"  # print bit at (x, y)
level1 |= mask(x, y)  # set bit at (x, y)
level1 &= ~mask(x, y)  # clear bit at (x, y)

với

def mask(x, y):
  return 1 << (WIDTH-x + y*WIDTH)

Nhưng điều đó chỉ hoạt động nếu các trường của bạn chỉ chứa 0 hoặc 1 tất nhiên. Nếu bạn cần nhiều giá trị hơn, bạn sẽ phải kết hợp một số bit khiến vấn đề trở nên phức tạp hơn nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.