Mengkonversi dict ke OrderedDict

138

Saya mengalami masalah dalam menggunakan collections.OrderedDictkelas. Saya menggunakan Python 2.7 di Raspbian, distro Debian untuk Raspberry Pi. Saya mencoba mencetak dua kamus untuk perbandingan (berdampingan) untuk petualangan teks. Urutan ini penting untuk membandingkan secara akurat. Apa pun yang saya coba, kamus cetak dengan cara yang tidak teratur seperti biasanya.

Inilah yang saya dapatkan ketika saya melakukannya di RPi saya:

import collections

ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship
# OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])

Jelas ada sesuatu yang tidak beres karena ia mencetak panggilan fungsi dan meletakkan kunci dan grup nilai ke dalam daftar bersarang ...

Inilah yang saya dapatkan dengan menjalankan sesuatu yang serupa pada PC saya:

import collections

Joe = {"Age": 28, "Race": "Latino", "Job": "Nurse"}
Bob = {"Age": 25, "Race": "White", "Job": "Mechanic", "Random": "stuff"}

#Just for clarity:
Joe = collections.OrderedDict(Joe)
Bob = collections.OrderedDict(Bob)

print Joe
# OrderedDict([('Age', 28), ('Race', 'Latino'), ('Job', 'Nurse')])
print Bob
# OrderedDict([('Age', 25), ('Race', 'White'), ('Job', 'Mechanic'), ('Random', 'stuff')])

Kali ini, ini sudah beres, tetapi seharusnya tidak mencetak hal-hal lain kan? (The memasukkannya ke dalam daftar dan menunjukkan panggilan fungsi.)

Di mana saya membuat kesalahan? Seharusnya tidak ada hubungannya dengan versi pi Python karena hanya versi Linux.

pythonpiboy
sumber
3
Catatan: OrderedDictdiurutkan berdasarkan urutan penyisipan, bukan urutan kunci alfanumerik.
el.pescado

Jawaban:

214

Anda membuat kamus terlebih dahulu , lalu meneruskan kamus itu ke OrderedDict. Untuk versi Python <3.6 (*) , saat Anda melakukan itu, pemesanan tidak lagi benar. dictsecara inheren tidak dipesan.

Sebagai gantinya, masukkan urutan tuple:

ship = [("NAME", "Albatross"),
        ("HP", 50),
        ("BLASTERS", 13),
        ("THRUSTERS", 18),
        ("PRICE", 250)]
ship = collections.OrderedDict(ship)

Apa yang Anda lihat ketika Anda mencetak OrderedDictadalah itu representasi , dan itu adalah sepenuhnya benar. OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])hanya menunjukkan kepada Anda, dalam representasi yang dapat direproduksi , apa isinya OrderedDict.


(*) : Dalam pelaksanaan CPython 3.6, yang dictjenis telah diupdate untuk menggunakan memori lebih struktur internal yang efisien yang memiliki efek samping bahagia menjaga ketertiban penyisipan, dan dengan perpanjangan kode yang ditunjukkan dalam karya pertanyaan tanpa masalah. Pada Python 3.7, spesifikasi bahasa Python telah diperbarui untuk mewajibkan semua implementasi Python harus mengikuti perilaku ini. Lihat jawaban saya yang lain ini untuk perincian dan juga mengapa Anda mungkin masih ingin menggunakan OrderedDict()untuk kasus-kasus tertentu.

Martijn Pieters
sumber
Ok jadi OrderedDict akan MENCIPTAKAN kamus untuk saya? Juga, untuk mencetak tanpa representasi yang dapat direproduksi, bisakah saya mencetak variabel yang menggunakan OrderedDict? yaitu: print ship ?? Terima kasih :)
pythonpiboy
3
Pertanyaan: Seperti yang Anda gambarkan, OrderedDict membuat "daftar" yang dipesan. Bukankah itu mengalahkan tujuannya? Itu hanya membuat daftar elemen, bukan kamus dengan kunci dan nilai ...
pythonpiboy
9
Jenisnya bertindak seperti keduanya; sebuah pemetaan yang mempertahankan ketertiban. Untuk membuatnya dengan pemesanan, Anda harus memberikannya secara berurutan . Karena dikte standar (pada apa pun selain PyPI atau Python 3.6+) tidak dapat melakukan itu, Anda memberikan daftar tuple sebagai gantinya. Setelah OrderedDictitu dibuat itu adalah kamus.
Martijn Pieters
4
Kedengarannya seperti kebingungan adalah dari mengasumsikan OrderedDict "menerapkan" pemesanan, bukan hanya mempertahankan pesanan. Saya tentu mengira itu akan mengurutkan input pada penciptaan - atau bahwa fungsi items () akan mengembalikan item yang diurutkan terlepas dari kapan mereka dimasukkan. Sebaliknya itu hanya membuat pemesanan apa pun yang Anda berikan.
whiterook6
2
@ whiterook6: ini bukan kamus yang diurutkan no. Ini adalah kamus berurutan, kamus yang mencatat urutan pasangan nilai kunci dan memungkinkan Anda memesan ulang pasangan itu. Bandingkan ini dengan daftar, yang merupakan urutan yang dipesan .
Martijn Pieters
36

Jika Anda tidak dapat mengedit bagian kode ini di mana definisi Anda ditetapkan, Anda masih dapat memesannya kapan saja dengan cara apa pun yang Anda inginkan, seperti ini:

from collections import OrderedDict

order_of_keys = ["key1", "key2", "key3", "key4", "key5"]
list_of_tuples = [(key, your_dict[key]) for key in order_of_keys]
your_dict = OrderedDict(list_of_tuples)
Jan Rozycki
sumber
11

Sebagian besar waktu kami menggunakan OrderedDict ketika kami membutuhkan pesanan khusus bukan yang umum seperti ASC dll.

Inilah solusi yang diusulkan:

import collections
ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship


new_dict = collections.OrderedDict()
new_dict["NAME"]=ship["NAME"]
new_dict["HP"]=ship["HP"]
new_dict["BLASTERS"]=ship["BLASTERS"]
new_dict["THRUSTERS"]=ship["THRUSTERS"]
new_dict["PRICE"]=ship["PRICE"]


print new_dict

Ini akan menjadi output:

OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])
OrderedDict([('NAME', 'Albatross'), ('HP', 50), ('BLASTERS', 13), ('THRUSTERS', 18), ('PRICE', 250)])

Catatan : Kamus yang diurutkan baru mempertahankan urutan pengurutannya ketika entri dihapus. Tetapi ketika kunci baru ditambahkan, kunci ditambahkan ke akhir dan jenisnya tidak dipertahankan. ( Dokumen resmi )

Abdul Majeed
sumber
2

Gunakan dict.items (); dapat sesederhana seperti berikut:

ship = collections.OrderedDict(ship.items())
Mohammad-Ali
sumber