Saya menulis program untuk mengatur urutan di mana berbagai objek akan muncul dalam laporan. Urutannya adalah posisi Y (sel) pada spreadsheet Excel.
Bagian demo kode ada di bawah. Yang ingin saya capai adalah memiliki koleksi, yang memungkinkan saya menambahkan beberapa objek dan saya bisa mendapatkan koleksi yang diurutkan berdasarkan urutannya.
SortedList list = new SortedList();
Header h = new Header();
h.XPos = 1;
h.name = "Header_1";
list.Add(h.XPos, h);
h = new Header();
h.XPos = 1;
h.name = "Header_2";
list.Add(h.XPos, h);
Saya tahu bahwa SortedList
kehendak tidak mengizinkan ini dan saya telah mencari alternatif. Saya tidak ingin menghilangkan duplikat dan sudah mencoba List<KeyValuePair<int, object>>
.
Terima kasih.
c#
.net
linq
collections
sortedlist
Mayur Kotlikar
sumber
sumber
List
?Jawaban:
Gunakan IComparer Anda sendiri!
Seperti yang sudah disebutkan di beberapa jawaban lain, Anda harus menggunakan kelas pembanding Anda sendiri. Untuk kepentingan ini saya menggunakan kelas IComparer generik, yang bekerja dengan apa pun yang mengimplementasikan IComparable:
Anda akan menggunakannya saat membuat instance SortedList baru, SortedDictionary, dll:
Di sini int adalah kunci yang bisa diduplikasi.
sumber
SortedDictionary
. Ini memungkinkan penghapusan juga.Anda dapat dengan aman menggunakan List <>. List memiliki metode Sort, yang kelebihan bebannya menerima IComparer. Anda dapat membuat kelas penyortir Anda sendiri sebagai. Berikut contohnya:
sumber
Saya menggunakan yang berikut ini:
Kasus uji saya:
Hasil:
sumber
Masalahnya adalah bahwa desain struktur data tidak sesuai dengan persyaratan: Perlu untuk menyimpan beberapa Header untuk XPos yang sama. Oleh karena itu,
SortedList<XPos, value>
sebaiknya tidak memiliki nilaiHeader
, tetapi memiliki nilaiList<Header>
. Ini adalah perubahan sederhana dan kecil, tetapi ini menyelesaikan semua masalah dan menghindari menciptakan masalah baru seperti solusi lain yang disarankan (lihat penjelasan di bawah):Harap dicatat bahwa menambahkan kunci "lucu", seperti menambahkan nomor acak atau berpura-pura bahwa 2 XPos dengan nilai yang sama berbeda menyebabkan banyak masalah lainnya. Misalnya menjadi sulit atau bahkan tidak mungkin untuk menghapus Header tertentu.
Perhatikan juga bahwa kinerja pengurutan jauh lebih baik jika hanya sedikit yang
List<Header>
harus diurutkan daripada setiapHeader
. Contoh: Jika ada 100 XPos dan masing-masing memiliki 100 tajuk, 10.000Header
perlu diurutkan, bukan 100List<Header>
.Tentu saja, solusi ini juga memiliki kelemahan: Jika ada banyak XPos dengan hanya 1 Header, maka banyak Daftar yang perlu dibuat, yang merupakan overhead.
sumber
Solusi paling sederhana (dibandingkan dengan semua hal di atas): gunakan
SortedSet<T>
, ia menerimaIComparer<SortableKey>
kelas, lalu terapkan metode Bandingkan dengan cara ini:sumber
Terima kasih banyak atas bantuannya. Saat mencari lebih banyak, saya menemukan solusi ini. (Tersedia di Stackoverflow.com untuk pertanyaan lain)
Pertama, saya membuat kelas yang akan merangkum objek saya untuk kelas (Headers, Footer dll)
Jadi kelas ini seharusnya menampung objek, dan PosX dari setiap objek menjadi Posisi int
Apa yang akhirnya saya dapatkan adalah daftar "Urutan" yang diurutkan.
sumber
Apakah Anda mencoba
Lookup<TKey, TElement>
yang akan mengizinkan kunci duplikat http://msdn.microsoft.com/en-us/library/bb460184.aspxsumber
Lookup
saya percaya. Ada cara bagus untuk mengatasi ini?ToLookup
apa sajaIEnumerable<T>
.Anda dapat menggunakan SortedList, gunakan nilai Anda untuk TKey, dan int (count) untuk TValue.
Berikut contohnya: Fungsi yang mengurutkan huruf dari sebuah kata.
sumber
Kelas koleksi ini akan mempertahankan duplikat dan menyisipkan tata urutan untuk duplikat. Triknya adalah memberi tag item dengan nilai unik saat disisipkan untuk menjaga tata urutan yang stabil. Kemudian kami membungkus semuanya dalam antarmuka ICollection.
kelas tes
Struktur pemberian tag
Pembantu pembanding lambda
sumber
Masalahnya adalah Anda menggunakan sesuatu sebagai kunci yang bukan kunci (karena itu terjadi beberapa kali).
Jadi jika Anda memiliki koordinat nyata, Anda mungkin harus mengambilnya
Point
sebagai kunci untuk SortedList Anda.Atau Anda membuat di
List<List<Header>>
mana indeks daftar pertama Anda mendefinisikan posisi-x dan daftar dalam mengindeks posisi-y (atau sebaliknya jika Anda suka).sumber
Kuncinya (permainan kata-kata) untuk ini adalah membuat
IComparable
kelas berbasis yang mempertahankan kesetaraan dan hashing, tetapi tidak pernah dibandingkan dengan 0 jika tidak sama. Ini dapat dilakukan, dan dapat dibuat dengan beberapa bonus - penyortiran stabil (yaitu, nilai yang ditambahkan ke daftar yang diurutkan terlebih dahulu akan mempertahankan posisinya), danToString()
dapat dengan mudah mengembalikan nilai string kunci yang sebenarnya.Inilah kunci struct yang harus melakukan trik:
sumber
Linq.Lookup itu keren dan semuanya, tetapi jika target Anda adalah hanya mengulang "kunci" sambil membiarkannya diduplikasi, Anda dapat menggunakan struktur ini:
Kemudian Anda bisa menulis:
HTH
sumber
Triknya adalah menambah objek Anda dengan kunci unik. Lihat tes berikut yang lolos. Saya ingin agar poin saya diurutkan berdasarkan nilai X-nya. Hanya menggunakan Point2D telanjang dalam fungsi perbandingan saya akan menyebabkan poin dengan nilai X yang sama dihilangkan. Jadi saya membungkus Point2D dalam kelas penandaan yang disebut Indexed.
Utilitas untuk membuat ini berhasil adalah
Pembanding yang membutuhkan lambda
Sebuah struktur penandaan
sumber
Beginilah cara saya memecahkan masalah. Ini dimaksudkan agar thread-aman meskipun Anda dapat menghapusnya
lock
jika Anda tidak membutuhkannya. Juga perhatikan arbitrerInsert
pada indeks tidak didukung karena dapat melanggar kondisi pengurutan.sumber
Buat kelas dan buat kueri daftarnya:
sumber
Inilah pendapat saya tentang ini. Awas, di sini mungkin ada komodo, C # masih tergolong baru buat saya.
Pemakaian:
sumber
Queue
di BCL, yang mewakili koleksi item pertama masuk, keluar pertama. Semantik kelas Anda berbeda. Kelas Anda memiliki permulaan (di mana item dikosongkan) tetapi tidak ada akhir (item dapat disisipkan di mana saja). JadiEnqueue
metode di kelas Anda adalah IMHO tidak ada artinya.PriorityQueue
akan lebih sesuai namanya.-2 * 5 == +10
), jadi ini bukan masalah besar. :-)