Saya sering harus memilah kamus, terdiri dari kunci-kunci & nilai-nilai, dengan nilai. Sebagai contoh, saya memiliki sebuah hash kata-kata dan frekuensi masing-masing, yang saya ingin memesan dengan frekuensi.
Ada SortedList
yang baik untuk nilai tunggal (misalnya frekuensi), yang saya ingin peta ini kembali ke kata.
Sorteddictionarystruktur perintah dengan kunci, bukan nilai. Beberapa resor untuk kelas kustom, tetapi ada cara yang lebih bersih?
Gunakan:
using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();
myList.Sort(
delegate(KeyValuePair<string, string> pair1,
KeyValuePair<string, string> pair2)
{
return pair1.Value.CompareTo(pair2.Value);
}
);
Karena anda're penargetan .NET 2.0 atau di atas, anda dapat menyederhanakan ini ke lambda sintaks-itu's setara, tapi lebih pendek. Jika anda're penargetan .NET 2.0 anda hanya dapat menggunakan sintaks ini jika anda're menggunakan compiler dari Visual Studio 2008 (atau di atas).
var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));
Menggunakan LINQ:
Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);
var sortedDict = from entry in myDict orderby entry.Value ascending select entry;
Ini juga akan memungkinkan untuk fleksibilitas yang besar dalam yang dapat anda pilih top 10, 20 10%, dll. Atau jika anda menggunakan kata-kata anda frequency index for jenis-depan
, anda bisa juga mencakup StartsWith
klausul juga.
Melihat sekeliling, dan menggunakan C# 3.0 fitur yang dapat kita lakukan ini:
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
Ini adalah terbersih cara saya've melihat dan mirip dengan Ruby cara penanganan hash.
Anda dapat mengurutkan Kamus dengan nilai dan menyimpannya kembali ke dirinya sendiri (sehingga ketika anda foreach lebih dari itu nilai-nilai yang keluar dalam urutan):
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
Tentu, hal itu mungkin tidak benar, tapi itu bekerja.
Pada tingkat tinggi, anda tidak memiliki pilihan lain selain untuk berjalan melalui seluruh Kamus dan melihat masing-masing nilai.
Mungkin ini bisa membantu: http://bytes.com/forum/thread563638.html Copy/Paste dari John Timney:
`` c# Kamus<string, string> s = baru Kamus<string, string>(); s.Tambahkan("1", "Item"); s.Tambahkan("2", "c Item"); s.Tambahkan("3", "b Item");
Daftar<KeyValuePair<string, string>> myList = new Daftar<KeyValuePair<string, string>>(s); myList.Mengurutkan( mendelegasikan(KeyValuePair<string, string> firstPair, KeyValuePair<string, string> nextPair) { kembali firstPair.Nilai.CompareTo(nextPair.Nilai); } ); ``
Anda'd pernah bisa semacam kamus pokoknya. Mereka tidak benar-benar memesan. Jaminan untuk sebuah kamus adalah bahwa kunci dan nilai koleksi yang iterable, dan nilai-nilai yang dapat diambil oleh index atau key, tapi tidak ada jaminan dari setiap urutan tertentu. Oleh karena itu anda akan perlu untuk mendapatkan nama pasangan nilai ke dalam daftar.
Anda tidak mengurutkan entri dalam Kamus. Kamus kelas .NET diimplementasikan sebagai hashtable - struktur data tidak diurutkan berdasarkan definisi.
Jika anda perlu untuk dapat iterate atas koleksi anda (dengan kunci) - anda perlu menggunakan Sorteddictionarystruktur, yang diimplementasikan sebagai sebuah Pohon Pencarian Biner.
Dalam kasus anda, namun sumber struktur adalah tidak relevan, karena hal ini diurutkan berdasarkan bidang yang berbeda. Anda masih akan perlu untuk menyortir berdasarkan frekuensi dan memasukkannya ke dalam koleksi baru diurutkan berdasarkan bidang yang relevan (frekuensi). Jadi dalam koleksi ini frekuensi adalah kunci dan kata-kata adalah nilai-nilai. Karena banyak kata-kata dapat memiliki frekuensi yang sama (dan anda akan menggunakannya sebagai kunci) anda tidak dapat menggunakan baik Kamus atau Sorteddictionarystruktur (mereka memerlukan kunci unik). Hal ini membuat anda dengan SortedList.
Saya don't mengerti mengapa anda bersikeras mempertahankan link ke item aslinya di utama/kamus pertama.
Jika benda-benda koleksi anda memiliki struktur yang lebih kompleks (bidang) dan anda dibutuhkan untuk dapat secara efisien akses/mengurutkan mereka menggunakan beberapa bidang yang berbeda sebagai kunci - Anda mungkin akan membutuhkan kustom struktur data yang akan terdiri dari penyimpanan utama yang mendukung O(1) penyisipan dan penghapusan (LinkedList) dan beberapa pengindeksan struktur - Kamus/SortedDictionaries/SortedLists. Indeks ini akan menggunakan salah satu bidang dari kompleks kelas sebagai kunci dan pointer/referensi LinkedListNode
Anda akan perlu untuk mengkoordinasikan insersi dan serapan grk untuk menjaga indeks anda di sync dengan koleksi utama (LinkedList) dan serapan grk akan cukup mahal saya'd pikirkan. Hal ini mirip dengan bagaimana database indeks bekerja - mereka yang fantastis untuk lookup tapi mereka menjadi beban ketika anda perlu untuk melakukan banyak insetions dan penghapusan.
Semua hal di atas hanya dibenarkan jika anda akan melakukan beberapa melihat-up berat pengolahan. Jika anda hanya perlu untuk output mereka setelah diurutkan berdasarkan frekuensi maka anda bisa menghasilkan sebuah daftar (anonim) tupel:
var dict = new SortedDictionary<string, int>();
// ToDo: populate dict
var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();
foreach (var entry in output)
{
Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
Mengurutkan nilai-nilai
Ini menunjukkan bagaimana untuk mengurutkan nilai-nilai dalam Kamus. Kita melihat konsol anda dapat mengkompilasi program di Visual Studio dan lari. Ia menambahkan tombol ke Kamus dan kemudian memilah mereka berdasarkan nilai-nilai mereka. Ingat bahwa Kamus kasus yang awalnya tidak diurutkan dalam cara apapun. Kami menggunakan LINQ orderby kata kunci dalam sebuah pernyataan permintaan.
OrderBy Klausa Program yang jenis Kamus [C#]
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// Example dictionary.
var dictionary = new Dictionary<string, int>(5);
dictionary.Add("cat", 1);
dictionary.Add("dog", 0);
dictionary.Add("mouse", 5);
dictionary.Add("eel", 3);
dictionary.Add("programmer", 2);
// Order by values.
// ... Use LINQ to specify sorting by value.
var items = from pair in dictionary
orderby pair.Value ascending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
// Reverse sort.
// ... Can be looped over in the same way as above.
items = from pair in dictionary
orderby pair.Value descending
select pair;
}
}
Output
dog: 0
cat: 1
programmer: 2
eel: 3
mouse: 5
Atau untuk bersenang-senang anda bisa menggunakan beberapa LINQ ekstensi kebaikan:
var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
.ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));
Menyortir Sorteddictionarystruktur
daftar untuk mengikat ke ListView kontrol menggunakan VB.NET:
Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)
MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)
Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding
Public Property MyString As String
Public Property MyValue As Integer
End Class
XAML:
<ListView Name="MyDictionaryListView">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
Cara termudah untuk mendapatkan diurutkan Kamus adalah dengan menggunakan built in Sorteddictionarystruktur
kelas:
//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
sortedSections = new SortedDictionary<int, string>(sections);
}
sortedSections
akan berisi diurutkan versi bagian
Lain jawaban yang baik, jika semua yang anda inginkan adalah untuk memiliki "sementara" daftar diurutkan berdasarkan Nilai. Namun, jika anda ingin memiliki kamus diurutkan berdasarkan Kunci
yang otomatis synchronizes dengan kamus lain yang diurutkan berdasarkan Nilai
, anda bisa menggunakan Bijection<K1, K2>
kelas.
Bijection<K1, K2>
memungkinkan anda untuk menginisialisasi koleksi dengan dua ada kamus, jadi jika anda ingin salah satu dari mereka yang akan disortir, dan anda ingin yang lain yang akan diurutkan, anda bisa membuat bijection dengan kode seperti
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
Anda dapat menggunakan dict
seperti kamus (itu menerapkan IDictionary<K, V>
), dan kemudian memanggil dict.Terbalik
untuk mendapatkan "inverse" kamus yang diurutkan berdasarkan Nilai
.
Bijection<K1, K2>
ini adalah bagian dari Loyc.Collections.dll, tetapi jika anda ingin, anda hanya bisa copy source code ke dalam proyek anda sendiri.
Note: jika ada beberapa kunci dengan nilai yang sama, anda dapat't menggunakan Bijection
, tapi anda dapat secara manual menyinkronkan antara biasa Kamus<Kunci,Nilai>
dan BMultiMap<Value,Key>
.
Misalkan kita memiliki sebuah kamus sebagai
Dictionary<int, int> dict = new Dictionary<int, int>();
dict.Add(21,1041);
dict.Add(213, 1021);
dict.Add(45, 1081);
dict.Add(54, 1091);
dict.Add(3425, 1061);
sict.Add(768, 1011);
sementara kamus untuk menyimpan nilai-nilai sebagai
: Dictionary<int, int> dctTemp = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value))
{
dctTemp .Add(pair.Key, pair.Value);
}
Sebenarnya di C#, Kamus berkat memiliki sort() metode, seperti yang anda lebih tertarik di urutkan berdasarkan nilai-nilai, anda bisa mendapatkan nilai sampai anda memberikan mereka kunci, singkatnya, anda perlu untuk iterate melalui mereka, menggunakan LINQ's Order By,
var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);
// Call OrderBy method here on each item and provide them the ids.
foreach (var item in items.OrderBy(k => k.Key))
{
Console.WriteLine(item);// items are in sorted order
}
anda dapat melakukan salah satu trik,
var sortedDictByOrder = items.OrderBy(v => v.Value);
atau
var sortedKeys = from pair in dictName
orderby pair.Value ascending
select pair;
juga tergantung pada apa nilai-nilai anda menyimpan,
itu tunggal (seperti string, int) atau ganda (seperti Daftar, Array, yang ditetapkan pengguna kelas),
jika satu anda dapat membuat daftar itu kemudian menerapkan semacam.
jika pengguna didefinisikan kelas,
maka class tersebut harus mengimplementasikan IComparable,
ClassName: IComparable<ClassName>
menimpa compareTo(ClassName c)
karena mereka lebih cepat dari LINQ, dan lebih banyak berorientasi objek.
Anda dapat mengurutkan Kamus dengan nilai dan mendapatkan hasil dalam kamus menggunakan kode di bawah ini:
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);