Cara yang tepat untuk menginisialisasi OrderedDict menggunakan konstruktornya sehingga mempertahankan urutan data awal?

124

Apa cara yang benar untuk menginisialisasi kamus berurutan (OD) sehingga mempertahankan urutan data awal?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

Pertanyaan:

  • Akankah OrderedDictmempertahankan urutan daftar tupel, atau tupel tupel atau tupel daftar atau daftar daftar, dll. Diteruskan pada saat inisialisasi (contoh ke-2 & ke-3 di atas)?

  • Bagaimana cara memverifikasi jika OrderedDictbenar-benar mempertahankan pesanan? Karena a dictmemiliki urutan yang tidak dapat diprediksi, bagaimana jika vektor pengujian saya untungnya memiliki urutan awal yang sama dengan urutan dikt yang tidak dapat diprediksi? Misalnya, jika alih-alih d = OrderedDict({'b':2, 'a':1})saya menulis d = OrderedDict({'a':1, 'b':2}), saya dapat secara keliru menyimpulkan bahwa pesanan dipertahankan. Dalam kasus ini, saya menemukan bahwa a dictdiurutkan menurut abjad, tetapi itu mungkin tidak selalu benar. Apa cara yang dapat diandalkan untuk menggunakan counterexample untuk memverifikasi apakah struktur data mempertahankan urutan atau tidak, singkatnya mencoba vektor uji berulang kali hingga satu rusak?

PS Saya akan meninggalkan ini di sini untuk referensi : "The OrderedDict konstruktor dan update () metode keduanya menerima argumen kata kunci, tetapi urutan mereka hilang karena fungsi Python panggilan semantik argumen kata kunci pass-in menggunakan kamus tidak berurutan biasa"

PPS: Mudah-mudahan, di masa mendatang, OrderedDict juga akan mempertahankan urutan kwargs (contoh 1): http://bugs.python.org/issue16991

klik
sumber
10
Sungguh ironis bahwa menginisialisasi OrderedDict dengan dikt (tidak kosong) adalah hal yang salah untuk dilakukan ... bisa dibilang itu akan menghasilkan Peringatan karena mungkin melanggar maksud pengguna.
smci
3
Setelah python3.6, OrderDict(b=2, a=1)juga merupakan cara yang tepat. Lihat PEP 468 .
IvanaGyro

Jawaban:

90

OrderedDict akan mempertahankan pesanan apa pun yang aksesnya dimiliki. Satu-satunya cara untuk meneruskan data yang diurutkan ke sana untuk diinisialisasi adalah dengan meneruskan daftar (atau, lebih umum, sebuah iterable) pasangan nilai kunci, seperti dalam dua contoh terakhir Anda. Seperti yang dikatakan oleh dokumentasi yang Anda tautkan, OrderedDict tidak memiliki akses ke urutan apa pun ketika Anda meneruskan argumen kata kunci atau argumen dict, karena setiap urutan di sana akan dihapus sebelum konstruktor OrderedDict melihatnya.

Perhatikan bahwa menggunakan pemahaman daftar di contoh terakhir Anda tidak mengubah apa pun. Tidak ada perbedaan antara OrderedDict([(i,i) for i in l])dan OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')]). Pemahaman daftar dievaluasi dan membuat daftar dan diteruskan; OrderedDict tidak tahu apa-apa tentang bagaimana itu dibuat.

BrenBarn
sumber
74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

Ya, itu akan berhasil. Menurut definisi, daftar selalu diurutkan seperti yang direpresentasikan. Ini juga berlaku untuk pemahaman daftar, daftar yang dihasilkan sama dengan cara data disediakan (yaitu, sumber dari daftar akan bersifat deterministik, bersumber dari a setatau dicttidak banyak).

Bagaimana cara seseorang memverifikasi jika OrderedDictbenar-benar mempertahankan pesanan. Karena sebuah dict memiliki urutan yang tidak dapat diprediksi, bagaimana jika vektor pengujian saya untungnya memiliki urutan awal yang sama dengan urutan yang tidak dapat diprediksi dari sebuah dict ?. Misalnya, jika alih-alih d = OrderedDict({'b':2, 'a':1})saya menulis d = OrderedDict({'a':1, 'b':2}), saya dapat secara keliru menyimpulkan bahwa pesanan dipertahankan. Dalam kasus ini, saya menemukan bahwa a dictberurutan menurut abjad, tetapi itu mungkin tidak selalu benar. yaitu, apa cara yang dapat diandalkan untuk menggunakan contoh penghitung untuk memverifikasi jika struktur data mempertahankan urutan atau tidak mencoba menguji vektor berulang kali hingga salah satu rusak.

Anda menyimpan daftar sumber 2-tupel untuk referensi, dan menggunakannya sebagai data pengujian untuk kasus pengujian Anda saat melakukan pengujian unit. Ulangi melalui mereka dan pastikan pesanan dipertahankan.

metatoaster
sumber
Tentang memverifikasi pesanan: Bagaimana cara memastikan bahwa 2-tupel saya AKAN merusak urutan dikt jika tidak dapat diprediksi? Ini adalah pertanyaan umum tentang struktur data apa pun, mungkin saya harus memisahkannya dari pertanyaan ini.
klik
1
Anda tidak dapat secara deterministik merusak sesuatu yang tidak bersifat deterministik.
metatoaster
1
Jadi apa pendekatan yang tepat untuk menguji hal-hal seperti itu? Anda terus mencoba tanpa batas waktu? Urutannya tidak dapat diprediksi untuk programmer, tetapi karena ini adalah peta hash, itu mengikuti algoritma 'beberapa' & tes yang benar harus mencoba untuk mengatasinya?
klik
2
Lihat __hash__. Khususnya tentang strtipe.
metatoaster
Menurut definisi, daftar selalu diurutkan seperti yang direpresentasikan. Ini adalah pernyataan kunci bagi saya. Saya memutuskan untuk hanya menggunakan daftar 2-tupel untuk dasar saya OrderedDictsehingga saya tidak memiliki biaya tambahan untuk mengubah daftar menjadi OrderedDict. Saya hanya mengulang elemen-elemen seperti daftar, bukan kamus.
Bobort