Saya mencoba untuk mengelompokkan string biner angka-angka tertentu berdasarkan berapa banyak 1 yang ada dalam string.
Ini tidak berfungsi:
s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]
one_groups = dict.fromkeys(range(5), [])
for x in binaries:
one_groups[x.count('1')] += [x]
Kamus yang diharapkan one_groups
perlu
{0: ['0000'],
1: ['0001', '1000'],
2: ['0011', '1001'],
3: ['0111', '1011'],
4: ['1111']}
Tapi saya mengerti
{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}
Sejauh ini satu-satunya hal yang berhasil adalah jika saya menggunakan one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]
alih-alihone_groups[x.count('1')] += [x]
Tapi mengapa begitu? Jika saya ingat dengan benar, bukankah dict[key]
seharusnya mengembalikan nilai kamus itu, mirip dengan cara dict.get(key)
kerjanya? Saya telah melihat utas ini Mengapa dict.get (kunci) alih-alih dict [kunci]? tetapi tidak menjawab pertanyaan saya untuk kasus khusus ini, karena saya tahu pasti program ini tidak dimaksudkan untuk mendapatkanKeyError
Saya juga sudah mencoba one_groups[x.count('1')].append(x)
tetapi ini tidak berhasil.
sumber
get
kembaliNone
jika kunci tidak ada atau nilai default yang disediakan, sementara operator indeks[]
meningkatkan kesalahan jika kunci tidak ada.bin(x)[2:].rjust(4, '0')
bisa disederhanakan menjadi'{:0>4b}'.format(x)
.binaries
tidak relevan dengan pertanyaan, jadi Anda bisa memberikan nilainya.Jawaban:
Masalahnya adalah mutabilitas:
one_groups = dict.fromkeys(range(5), [])
- ini melewati daftar yang sama dengan nilai untuk semua kunci . Jadi, jika Anda mengubah satu nilai, Anda mengubah semuanya.Pada dasarnya sama dengan mengatakan:
Jika Anda ingin menggunakan daftar baru, Anda perlu melakukannya dalam satu lingkaran - baik
for
lingkaran eksplisit atau dalam pemahaman dict:Hal ini akan "mengeksekusi"
[]
(yang sama denganlist()
) untuk setiap kunci, sehingga membuat nilainya dengan daftar yang berbeda.Kenapa
get
berhasil? Karena Anda secara eksplisit mengambil daftar saat ini, tetapi+
membuat daftar hasil baru. Dan tidak masalah apakah ituone_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]
atauone_groups[x.count('1')] = one_groups[x.count('1')] + [x]
- yang penting ada+
.Saya tahu bagaimana semua orang mengatakan
a+=b
adila=a+b
, tetapi implementasinya mungkin berbeda untuk optimasi - jika daftar,+=
hanya.extend
karena kami tahu kami ingin hasil kami dalam variabel saat ini, jadi membuat daftar baru akan membuang-buang memori.sumber
mylist = [[] * 5] * 5
dan bagaimanamylist = [[] for x in range(5)] * 5
memperbaikinya. Hanya untuk klarifikasi cepat, dari yang saya mengerti, ini terjadi karena variabel yang menunjuk ke alamat memori daftar kosong itu. Apakah ini juga berarti masalah tidak akan terjadi jika saya menggunakan primitif?one_groups[x.count('1')] += [x]
karena Anda tidak dapat menambahkan daftar ke tipe primitif. Solusi yang lebih baik adalah dengan menggunakan defaultdict sebagai gantinya.+
panggilan__add__
dan mengembalikan objek baru, sementara+=
panggilan__iadd__
, dan tidak diharuskan untuk mengembalikan objek baruMasalahnya menggunakan
one_groups = dict.fromkeys(range(5), [])
(Ini melewati daftar yang sama dengan nilai untuk semua kunci. Jadi jika Anda mengubah satu nilai, Anda mengubah semuanya)
Anda bisa menggunakan ini sebagai gantinya:
one_groups = {i:[] for i in range(5)}
(Hal ini akan "mengeksekusi" [] (yang sama dengan daftar ()) untuk setiap kunci, sehingga membuat nilai dengan daftar yang berbeda.)
sumber
Ini adalah bantuan pada
fromkeys
metode dikt .Yang mengatakan bahwa fromkey akan menerima nilai, dan bahkan itu adalah callable, itu akan mengevaluasinya terlebih dahulu, dan kemudian menetapkan nilai itu ke semua kunci dikt.
Daftar bisa berubah dalam Python, dan itu akan menetapkan referensi daftar kosong yang sama dan satu perubahan akan mempengaruhi semuanya.
Gunakan defaultdict sebagai gantinya:
Ini akan menerima penugasan untuk kunci yang tidak ada dan nilai akan default ke daftar kosong (dalam hal ini).
sumber