Ingatlah bahwa daftar tidak diimplementasikan sebagai daftar tertaut tunggal di Python, jadi operasi ini mahal (seperti dalam: seluruh daftar perlu disalin). Bergantung pada apa yang ingin Anda capai, ini mungkin atau mungkin tidak menjadi masalah. Saya hanya menyebutkan itu karena jenis penghancuran daftar ini sering ditemukan dalam bahasa fungsional, yang sebenarnya merupakan operasi yang sangat murah.
Niklas B.
Jawaban:
192
Di bawah Python 3.x, Anda dapat melakukan ini dengan baik:
Fitur baru di 3.x adalah menggunakan *operator dalam membongkar, yang berarti nilai tambahan apa pun. Ini dijelaskan dalam PEP 3132 - Extended Iterable Unpacking . Ini juga memiliki keuntungan untuk mengerjakan iterable apa pun, bukan hanya urutan.
Ini juga sangat mudah dibaca.
Seperti dijelaskan dalam PEP, jika Anda ingin melakukan hal yang setara di bawah 2.x (tanpa berpotensi membuat daftar sementara), Anda harus melakukan ini:
it = iter(iterable)
head, tail = next(it), list(it)
Seperti disebutkan dalam komentar, ini juga memberikan kesempatan untuk mendapatkan nilai default headdaripada membuat pengecualian. Jika Anda menginginkan perilaku ini, gunakan next()argumen opsional kedua dengan nilai default, yang next(it, None)akan memberi Anda Nonejika tidak ada elemen head.
Biasanya, jika Anda mengerjakan daftar, cara termudah tanpa sintaks 3.x adalah:
maaf, saya menggunakan istilah ekor secara tidak benar. Maksud saya apa yang saya katakan dalam contoh, itu adalah daftar tanpa elemen pertama
Giacomo d'Antonio
1
@NikolayFominyh Keduanya sama - keduanya mengambil elemen head dan membuat daftar baru yang berisi elemen ekor. Tidak ada perbedaan dalam kompleksitas. Kelas lain bisa mengimplementasikan __getitem__/ __setitem__melakukan operasi tail dengan malas, tetapi daftar bawaan tidak.
Gareth Latty
2
Pada daftar 800 elemen yang melakukannya 1 juta kali, saya memiliki 2,8s untuk head, solusi * tail = seq dan hanya 1,8s untuk solusi head, tail = seq [0], seq [1:]. Mengiris masih lebih cepat untuk daftar.
Cabu
2
@CMCDragonkai Tidak, kelas daftar utama Python adalah daftar larik. Ini akan menjadi O (n) karena ini melibatkan penyalinan ekor ke daftar baru (dengan satu O (1) get untuk kepala).
Gareth Latty
1
Sintaks yang bagus ini adalah alasan lain untuk pindah kepython 3.x
Sepertinya deque (list_instance) memiliki kompleksitas O (N). Apakah aku salah?
Никита Конин
1
@ НикитаКонин, Anda benar tentang konstruksi deque. Namun, jika Anda ingin mengakses elemen pertama lebih dari satu kali, maka head, tail = l.popleft(), l~ O (1). head, tail = seq[0], seq[1:]adalah O (n).
Nikolay Fominyh
Sepertinya Anda bisa melakukannya head = l.popleft()dan tailhanya alias untuk l. Jika lperubahan tailperubahan juga.
mengapa di dunia ini Anda melakukan ini, bukan hanya head, tail = lst[0], lst[1:]? jika OP berarti menggunakan literal maka dia bisa membelah kepala dan ekor secara manualhead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
Filipe Pina
1
(1) Pertanyaan Op adalah apakah mungkin melakukan ini dalam satu baris (jadi tidak lst = ...di baris sebelumnya). (2) Melakukan head, tail = lst[0], lst[1:]membuat kode terbuka untuk efek samping (pertimbangkan head, tail = get_list()[0], get_list()[1:]), dan berbeda dari bentuk Op head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55].
BobIsNotMyName
Karena itu, saya mengakui bahwa ini adalah cara yang tidak jelas untuk mendapatkan kepala / ekor. Tapi saya pikir itu adalah jawaban terbaik untuk Python 2 untuk pertanyaan spesifik Op.
BobIsNotMyName
1
Membangun solusi Python 2 dari @GarethLatty , berikut ini adalah cara untuk mendapatkan satu baris yang setara tanpa variabel perantara di Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Jika Anda membutuhkannya untuk menjadi pengecualian-bukti (yaitu mendukung daftar kosong), maka tambahkan:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Jika Anda ingin melakukannya tanpa titik koma, gunakan:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]
Jawaban:
Di bawah Python 3.x, Anda dapat melakukan ini dengan baik:
>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> head 1 >>> tail [1, 2, 3, 5, 8, 13, 21, 34, 55]
Fitur baru di 3.x adalah menggunakan
*
operator dalam membongkar, yang berarti nilai tambahan apa pun. Ini dijelaskan dalam PEP 3132 - Extended Iterable Unpacking . Ini juga memiliki keuntungan untuk mengerjakan iterable apa pun, bukan hanya urutan.Ini juga sangat mudah dibaca.
Seperti dijelaskan dalam PEP, jika Anda ingin melakukan hal yang setara di bawah 2.x (tanpa berpotensi membuat daftar sementara), Anda harus melakukan ini:
Seperti disebutkan dalam komentar, ini juga memberikan kesempatan untuk mendapatkan nilai default
head
daripada membuat pengecualian. Jika Anda menginginkan perilaku ini, gunakannext()
argumen opsional kedua dengan nilai default, yangnext(it, None)
akan memberi AndaNone
jika tidak ada elemen head.Biasanya, jika Anda mengerjakan daftar, cara termudah tanpa sintaks 3.x adalah:
head, tail = seq[0], seq[1:]
sumber
__getitem__
/__setitem__
melakukan operasi tail dengan malas, tetapi daftar bawaan tidak.python 3.x
>>> mylist = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] >>> head, tail = mylist[0], mylist[1:] >>> head 1 >>> tail [1, 2, 3, 5, 8, 13, 21, 34, 55]
sumber
Untuk kompleksitas
head,tail
operasi O (1), Anda harus menggunakandeque
.Cara berikut:
from collections import deque l = deque([1,2,3,4,5,6,7,8,9]) head, tail = l.popleft(), l
Ini berguna ketika Anda harus mengulangi semua elemen daftar. Misalnya dalam menggabungkan 2 partisi secara naif dalam merge sort.
sumber
head, tail = l.popleft(), l
~ O (1).head, tail = seq[0], seq[1:]
adalah O (n).head = l.popleft()
dantail
hanya alias untukl
. Jikal
perubahantail
perubahan juga.Python 2, menggunakan lambda
>>> head, tail = (lambda lst: (lst[0], lst[1:]))([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]) >>> head 1 >>> tail [1, 2, 3, 5, 8, 13, 21, 34, 55]
sumber
head, tail = lst[0], lst[1:]
? jika OP berarti menggunakan literal maka dia bisa membelah kepala dan ekor secara manualhead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
lst = ...
di baris sebelumnya). (2) Melakukanhead, tail = lst[0], lst[1:]
membuat kode terbuka untuk efek samping (pertimbangkanhead, tail = get_list()[0], get_list()[1:]
), dan berbeda dari bentuk Ophead, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
.Membangun solusi Python 2 dari @GarethLatty , berikut ini adalah cara untuk mendapatkan satu baris yang setara tanpa variabel perantara di Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Jika Anda membutuhkannya untuk menjadi pengecualian-bukti (yaitu mendukung daftar kosong), maka tambahkan:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Jika Anda ingin melakukannya tanpa titik koma, gunakan:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]
sumber