Ubah tuple ke daftar dan kembali

206

Saat ini saya sedang mengerjakan editor peta untuk game di pygame, menggunakan peta ubin. Level dibangun dari balok dalam struktur berikut (meskipun jauh lebih besar):

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))

di mana "1" adalah blok yang merupakan tembok dan "0" adalah blok yang kosong.

Kode berikut pada dasarnya adalah yang menangani perubahan tipe blok:

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

Tetapi karena level disimpan dalam tuple, saya tidak dapat mengubah nilai dari blok yang berbeda. Bagaimana cara saya mengubah nilai yang berbeda di level dengan cara yang mudah?

pengguna2133308
sumber
12
jangan menggunakan tuple, cukup gunakan daftar dari awal. Ini mungkin benar-benar memperlambat kode Anda jika level Anda besar, jika Anda harus terus mengubahnya
jamylak
4
bagaimana dengan daftar alih-alih tupel dari awal?
Krzysztof Bujniewicz
4
@ user2133308 btw hanya catatan kompatibilitas, Anda harus menggunakan pembagian integer //bukan hanya /karena di Python 3, /akan melakukan pembagian titik mengambang dan mengacaukan kode Anda.
jamylak

Jawaban:

284

Konversikan tuple ke daftar:

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

Konversi daftar menjadi tuple:

>>> l = ['my', 'name', 'is', 'mr', 'list']
>>> l
['my', 'name', 'is', 'mr', 'list']
>>> tuple(l)
('my', 'name', 'is', 'mr', 'list')
Khonix
sumber
5
Ini tidak bekerja untuk saya. Jika saya menjalankan kode di blok pertama untuk mengonversi tuple t ke daftar dengan mengirimkan t ke daftar (), saya mendapatkan pesan kesalahan: "*** Kesalahan dalam argumen: '(t)'" Ini sepertinya terjadi pada saya hanya saat debugging. Masih bingung.
Jimmy
4
@ Jimmy itu karena daftar adalah perintah debugger, jalankan p list(...)saja.
moritz
74

Anda memiliki tuple tuple.
Untuk mengonversi setiap tuple ke daftar:

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

--- ATAU ---

map(list, level)

Dan setelah Anda selesai mengedit, cukup konversikan kembali:

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

--- ATAU --- (Terima kasih @jamylak)

tuple(itertools.imap(tuple, edited))

Anda juga dapat menggunakan larik 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]])

Untuk memanipulasi:

if clicked[0] == 1:
    x = (mousey + cameraY) // 60 # For readability
    y = (mousex + cameraX) // 60 # For readability
    a[x][y] = 1
pradyunsg
sumber
2
NumPy adalah paket dasar untuk komputasi ilmiah dengan Python. Objek utama NumPy adalah array multidimensi yang homogen. Ini adalah tabel elemen (biasanya angka), semua dari jenis yang sama, diindeks oleh tupel bilangan bulat positif.
pradyunsg
24

Anda dapat memiliki daftar daftar. Ubah tupel tupel Anda menjadi daftar daftar menggunakan:

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

atau

level1 = map(list, level1)

dan memodifikasinya sesuai.

Tapi array numpy lebih dingin.

eumiro
sumber
18

Untuk mengonversi tuple ke daftar

(Koma tidak ada di antara tupel dalam pertanyaan yang diberikan, ditambahkan untuk mencegah pesan kesalahan)

Metode 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)

Metode 2:

level1 = map(list,level1)

print(list(level1))

Metode 1 mengambil --- 0,0019991397857666016 detik ---

Metode 2 mengambil --- 0,0010001659393310547 detik ---

Aravind Krishnakumar
sumber
14

Mengapa Anda tidak mencoba mengubah tipenya dari tuple ke daftar dan sebaliknya.

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)
TheRedstoneLemon
sumber
5

Kedua jawaban itu baik, tetapi sedikit saran:

Tuples tidak berubah, yang menyiratkan bahwa mereka tidak dapat diubah. Jadi, jika Anda perlu memanipulasi data, lebih baik menyimpan data dalam daftar, itu akan mengurangi overhead yang tidak perlu.

Dalam kasus Anda, ekstrak data ke daftar, seperti yang ditunjukkan oleh eumiro, dan setelah memodifikasi buat tuple serupa struktur yang sama sebagai jawaban yang diberikan oleh Schoolboy.

Juga seperti yang disarankan menggunakan array numpy adalah opsi yang lebih baik

tanzil
sumber
Anda juga harus menulis dalam jawaban ini, yang numpyakan memberikan solusi tercepat untuk bekerja dengan tipe data ini.
jamylak
Tentu saja Anda dapat menggunakan struktur data yang tidak dapat diubah seperti tupel bahkan ketika Anda sedang memanipulasi data. Seluruh premis pemrograman fungsional dan semua yang sebagian besar dibangun berdasarkan data yang ada. Tapi tentu saja, di tanah Python Anda mungkin ingin pergi dengan massa dan bermutasi secara bebas ...
nperson325681
5

Daftar ke Tuple dan kembali dapat dilakukan seperti di bawah ini

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)
Vijay Rangarajan
sumber
2

Anda dapat secara dramatis mempercepat barang-barang Anda jika Anda hanya menggunakan satu daftar dan bukan daftar daftar. Ini tentu saja mungkin hanya jika semua daftar batin Anda memiliki ukuran yang sama (yang benar dalam contoh Anda, jadi saya hanya menganggap ini).

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)

Dan Anda bisa lebih cepat jika menggunakan bitfield daripada daftar:

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)

dengan

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

Tapi itu hanya berfungsi jika bidang Anda hanya berisi 0 atau 1 saja. Jika Anda membutuhkan lebih banyak nilai, Anda harus menggabungkan beberapa bit yang akan membuat masalah lebih rumit.

Alfe
sumber