2013-04-30 21 views
98

Tôi hiện đang làm việc trên trình chỉnh sửa bản đồ cho trò chơi trong trò đùa, sử dụng bản đồ lát. Mức được xây dựng lên ra khỏi khối trong cơ cấu như sau (mặc dù lớn hơn nhiều):Chuyển tuple thành danh sách và quay 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)) 

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

Các mã sau đây về cơ bản là một xử lý sự thay đổi của các loại khối:

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

Nhưng kể từ khi 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 cách nào để tôi thay đổi các giá trị khác nhau ở cấp độ một cách dễ dàng?

Chỉnh sửa: Đã giải quyết! Cảm ơn các bạn

+9

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

+3

làm thế nào về đi với danh sách thay vì tuples ngay từ đầu? –

+3

@ user2133308 btw chỉ là một lưu ý tương thích, bạn nên sử dụng phân 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à vặn mã của bạn. – jamylak

Trả lời

17

Bạn có thể có danh sách danh sách. Chuyển đổi tuple lại tuples vào một danh sách các danh sách sử dụng:

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

hoặc

level1 = map(list, level1) 

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

Nhưng numpy array thì lạnh hơn.

50

Bạn có một bộ tuple.
Để chuyển đổi tất cả các tuple vào một danh sách:

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

--- HAY ---

map(list, level) 

Và sau khi bạn đang thực hiện chỉnh sửa, 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]]) 

Đối với thao tác:

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

mảng numpy này là gì? giải thích xin vui lòng .. – eRaisedToX

+0

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

4

Cả hai câu trả lời là 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 được. 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 danh sách, như được hiển thị bằng eumiro và sau khi sửa đổi tạo một bộ tương tự có cấu trúc tương tự như câu trả lời được đưa ra bởi Schoolboy.

Cũng như đề nghị sử dụng mảng NumPy là một lựa chọn tốt hơn

+0

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

+0

Tất nhiên bạn có thể sử dụng các cấu trúc dữ liệu không thay đổi như tuples 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ả phần lớn được xây dựng trên sự kiên trì của dữ liệu. Nhưng tất nhiên, trong đất Python bạn có thể muốn đi với quần chúng và biến đổi một cách tự do ... – progo

1

Bạn có thể tăng tốc độ đáng kể lên công cụ của bạn nếu bạn sử dụng chỉ là một danh sách thay vì một danh sách liệt kê. Điều này có thể tất nhiên chỉ khi 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ả định đ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 có thể còn nhanh hơn nếu bạn sử dụng một bitfield thay vì một 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ỉ làm việc nếu lĩnh vực 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 phải kết hợp nhiều bit để làm cho vấn đề phức tạp hơn nhiều.

148

Chuyển đổi tuple vào danh sách:

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

danh sách Convert to tuple:

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

Tại sao bạn không thử chuyển đổi loại hình của nó từ một tuple vào một 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) 
+0

Ý tưởng tuyệt vời! –

10

Để chuyển đổi các bộ liệt kê

(Dấu phẩy bị mất tích giữa các bản ghi trong các câu hỏi được đưa ra, nó đã được bổ sung để ngăn chặn thông báo lỗi)

Phương pháp 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) 

Phương pháp 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 ---