Saya sering harus mengurutkan kamus, yang terdiri dari kunci & nilai, berdasarkan nilai. Sebagai contoh, saya memiliki hash kata dan frekuensi masing-masing, yang ingin saya pesan berdasarkan frekuensi.
Ada SortedList
yang bagus untuk nilai tunggal (katakanlah frekuensi), yang ingin saya petakan kembali ke kata.
Perintah SortedDictionary menurut kunci, bukan nilai. Beberapa resor ke kelas khusus , tetapi apakah ada cara yang lebih bersih?
c#
.net
sorting
dictionary
Kalid
sumber
sumber
IComparer
yang melakukan trik (benar bahwa itu menerima kunci untuk dibandingkan, tetapi dengan kunci, Anda bisa mendapatkan nilai). ;-)Jawaban:
Menggunakan:
Karena Anda menargetkan .NET 2.0 atau di atasnya, Anda dapat menyederhanakan ini menjadi sintaks lambda - ini setara, tetapi lebih pendek. Jika Anda menargetkan .NET 2.0, Anda hanya dapat menggunakan sintaks ini jika menggunakan kompiler dari Visual Studio 2008 (atau lebih tinggi).
sumber
myList.Sort((x,y)=>x.Value.CompareTo(y.Value));
IEnumerable
, sehingga kamu bisa mendapatkan daftar yang diurutkan seperti ini:var mySortedList = myDictionary.OrderBy(d => d.Value).ToList();
Gunakan LINQ:
Ini juga akan membuat Anda sangat fleksibel karena Anda dapat memilih 10, 20 10% teratas, dll. Atau jika Anda menggunakan indeks frekuensi kata untuk
type-ahead
, Anda juga dapat memasukkanStartsWith
klausa.sumber
IEnumerable<KeyValuePair<TKey, TValue>>
pengembalian harus atau aOrderedDictionary<TKey, TValue>
. Atau seseorang harus menggunakanSortedDictionary
dari awal. Untuk dataranDictionary
, MSDN dengan jelas menyatakan "Urutan pengembalian barang tidak ditentukan.". Tampaknya edit terakhir @ rythos42 yang harus disalahkan. :).ToDictionary
- kamus standar tidak menjamin urutansumber
Melihat sekeliling, dan menggunakan beberapa fitur C # 3.0 kita dapat melakukan ini:
Ini adalah cara terbersih yang pernah saya lihat dan mirip dengan cara Ruby menangani hash.
sumber
(for KeyValuePair<string, int> item in keywordCounts.OrderBy(key => key.Value) select item).ToDictionary(t => t.Key, t => t.Value)
- hanya tambahan kecil untuk jawaban Anda :) Terima kasih, btw :)Anda dapat mengurutkan Kamus berdasarkan nilai dan menyimpannya kembali ke dalam kamus itu sendiri (sehingga saat Anda memeriksa nilai-nilai tersebut secara berurutan):
Tentu, itu mungkin tidak benar, tetapi berhasil.
sumber
Pada level yang tinggi, Anda tidak punya pilihan lain selain menelusuri keseluruhan Kamus dan melihat setiap nilai.
Mungkin ini membantu: http://bytes.com/forum/thread563638.html Salin / Tempel dari John Timney:
sumber
Anda tidak akan pernah bisa mengurutkan kamus. Mereka sebenarnya tidak dipesan. Jaminan untuk kamus adalah bahwa kunci dan koleksi nilai dapat diubah, dan nilai dapat diambil dengan indeks atau kunci, tetapi tidak ada jaminan dari urutan tertentu. Karenanya Anda perlu memasukkan pasangan nilai nama ke dalam daftar.
sumber
Anda tidak mengurutkan entri dalam Kamus. Kelas kamus di .NET diimplementasikan sebagai hashtable - struktur data ini tidak dapat diurutkan berdasarkan definisi.
Jika Anda harus dapat mengulangi koleksi Anda (dengan kunci) - Anda perlu menggunakan SortedDictionary, yang diimplementasikan sebagai Binary Search Tree.
Dalam kasus Anda, namun struktur sumber tidak relevan, karena diurutkan berdasarkan bidang yang berbeda. Anda masih perlu mengurutkannya berdasarkan frekuensi dan memasukkannya ke dalam koleksi baru yang diurutkan berdasarkan bidang yang relevan (frekuensi). Jadi dalam koleksi ini frekuensinya adalah kunci dan kata-kata adalah nilai. Karena banyak kata dapat memiliki frekuensi yang sama (dan Anda akan menggunakannya sebagai kunci), Anda tidak dapat menggunakan Kamus maupun SortedDictionary (mereka memerlukan kunci unik). Ini meninggalkan Anda dengan SortedList.
Saya tidak mengerti mengapa Anda bersikeras mempertahankan tautan ke item asli di kamus utama / pertama Anda.
Jika objek dalam koleksi Anda memiliki struktur yang lebih kompleks (lebih banyak bidang) dan Anda harus dapat mengakses / mengurutkannya secara efisien menggunakan beberapa bidang berbeda sebagai kunci - Anda mungkin memerlukan struktur data khusus yang akan terdiri dari penyimpanan utama yang mendukung O (1) penyisipan dan penghapusan (LinkedList) dan beberapa struktur pengindeksan - Kamus / SortedDictionaries / SortedLists. Indeks ini akan menggunakan salah satu bidang dari kelas kompleks Anda sebagai kunci dan pointer / referensi ke LinkedListNode di LinkedList sebagai nilai.
Anda perlu mengoordinasikan penyisipan dan pemindahan untuk menjaga indeks Anda tetap sinkron dengan koleksi utama (LinkedList) dan pemindahan akan cukup mahal menurut saya. Ini mirip dengan cara kerja indeks basis data - mereka fantastis untuk pencarian tetapi mereka menjadi beban ketika Anda perlu melakukan banyak insetions dan delesi.
Semua hal di atas hanya dibenarkan jika Anda akan melakukan beberapa pencarian berat. Jika Anda hanya perlu menampilkannya sekali diurutkan berdasarkan frekuensi maka Anda bisa menghasilkan daftar tupel (anonim):
sumber
sumber
Atau untuk bersenang-senang Anda bisa menggunakan beberapa kebaikan ekstensi LINQ:
sumber
Mengurutkan
SortedDictionary
daftar untuk diikat ke dalamListView
kontrol menggunakan VB.NET:XAML:
sumber
Cara termudah untuk mendapatkan Kamus yang diurutkan adalah dengan menggunakan
SortedDictionary
kelas bawaan:sortedSections
akan berisi versi yang diurutkan darisections
sumber
SortedDictionary
urutkan berdasarkan kunci. OP ingin mengurutkan berdasarkan nilai.SortedDictionary
tidak membantu dalam hal ini.sorteddictionary()
selalu menang setidaknya 1 mikrodetik, dan lebih mudah untuk mengelola (karena overhead mengubahnya kembali menjadi sesuatu yang mudah berinteraksi dengan dan dikelola mirip dengan Kamus adalah 0 (sudah menjadisorteddictionary
)).Jawaban lain baik, jika semua yang Anda inginkan adalah memiliki daftar "sementara" diurutkan berdasarkan Nilai. Namun, jika Anda ingin memiliki kamus diurutkan menurut
Key
yang secara otomatis mensinkronisasikan dengan kamus lain yang diurutkan olehValue
, Anda bisa menggunakanBijection<K1, K2>
kelas .Bijection<K1, K2>
memungkinkan Anda untuk menginisialisasi koleksi dengan dua kamus yang ada, jadi jika Anda ingin salah satunya tidak diurutkan, dan Anda ingin yang lainnya diurutkan, Anda dapat membuat bijection Anda dengan kode sepertiAnda dapat menggunakan
dict
seperti kamus normal (yang mengimplementasikannyaIDictionary<K, V>
), dan kemudian menelepondict.Inverse
untuk mendapatkan kamus "terbalik" yang diurutkan berdasarkanValue
.Bijection<K1, K2>
adalah bagian dari Loyc.Collections.dll , tetapi jika Anda mau, Anda bisa menyalin kode sumber ke proyek Anda sendiri.Catatan : Seandainya ada beberapa kunci dengan nilai yang sama, Anda tidak bisa menggunakan
Bijection
, tetapi Anda bisa menyinkronkan secara manual antara yang biasaDictionary<Key,Value>
dan aBMultiMap<Value,Key>
.sumber
Misalkan kita memiliki kamus sebagai
1) Anda dapat menggunakan
temporary dictionary to store values as
:sumber
Sebenarnya dalam C #, Kamus tidak memiliki metode sort (), karena Anda lebih tertarik mengurutkan berdasarkan nilai, Anda tidak bisa mendapatkan nilai sampai Anda memberikannya kunci, singkatnya, Anda perlu mengulanginya, menggunakan Pesanan LINQ oleh,
Anda dapat melakukan satu trik,
atau
ini juga tergantung pada jenis nilai apa yang Anda simpan,
apakah itu tunggal (seperti string, int) atau beberapa (seperti Daftar, Array, kelas yang ditentukan pengguna),
jika lajang Anda dapat membuat daftar itu lalu menerapkan sortir.
jika kelas yang ditentukan pengguna, maka kelas itu harus mengimplementasikan IComparable,
ClassName: IComparable<ClassName>
dan menimpacompareTo(ClassName c)
karena mereka lebih cepat daripada LINQ, dan lebih berorientasi objek.sumber
Namespace yang dibutuhkan:
using System.Linq;
Dipesan oleh desc:
Dipesan oleh Asc:
sumber
Anda dapat mengurutkan Kamus berdasarkan nilai dan mendapatkan hasilnya dalam kamus menggunakan kode di bawah ini:
sumber
Mengingat Anda memiliki kamus, Anda dapat mengurutkannya langsung pada nilai menggunakan di bawah satu liner:
sumber