Saya memiliki daftar contoh kelas kasus skala sederhana dan saya ingin mencetaknya dalam urutan leksikografis yang dapat diprediksi menggunakan list.sorted
, tetapi menerima "Tidak ada Pengurutan implisit yang ditentukan untuk ...".
Apakah ada implisit yang menyediakan pengurutan leksikografis untuk kelas kasus?
Apakah ada cara idiomatik sederhana untuk menggabungkan pengurutan leksikografis ke dalam kelas kasus?
scala> case class A(tag:String, load:Int)
scala> val l = List(A("words",50),A("article",2),A("lines",7))
scala> l.sorted.foreach(println)
<console>:11: error: No implicit Ordering defined for A.
l.sorted.foreach(println)
^
Saya tidak senang dengan 'retasan':
scala> l.map(_.toString).sorted.foreach(println)
A(article,2)
A(lines,7)
A(words,50)
scala
sorting
case-class
ya_pulser
sumber
sumber
Jawaban:
Metode favorit pribadi saya adalah menggunakan pemesanan implisit yang disediakan untuk Tuple, karena jelas, ringkas, dan benar:
Ini bekerja karena pendamping untuk
Ordered
mendefinisikan konversi implisit dariOrdering[T]
keOrdered[T]
yang dalam lingkup untuk setiap kelas yang mengimplementasikanOrdered
. Adanya implisitOrdering
s untukTuple
s memungkinkan konversi dariTupleN[...]
menjadiOrdered[TupleN[...]]
asalkanOrdering[TN]
ada implisit untuk semua elemenT1, ..., TN
tupel, yang seharusnya selalu menjadi kasus karena tidak masuk akal untuk mengurutkan pada tipe data dengan noOrdering
.Pengurutan implisit untuk Tuple adalah tujuan Anda untuk skenario pengurutan apa pun yang melibatkan kunci sortir komposit:
Karena jawaban ini telah terbukti populer, saya ingin memperluasnya, dengan memperhatikan bahwa solusi yang menyerupai berikut ini dalam beberapa keadaan dapat dianggap kelas perusahaan ™:
Diberikan
es: SeqLike[Employee]
,es.sorted()
akan mengurutkan berdasarkan nama, danes.sorted(Employee.orderingById)
akan mengurutkan berdasarkan id. Ini memiliki beberapa manfaat:Ordering
, jadi menyediakan pengurutan secara langsung menghilangkan konversi implisit dalam banyak kasus.sumber
value compare is not a member of (String, Int)
.Ini memiliki keuntungan bahwa itu diperbarui secara otomatis setiap kali A berubah. Namun, kolom A harus ditempatkan sesuai urutan penggunaannya.
sumber
<console>:12: error: not found: value unapply
Untuk meringkas, ada tiga cara untuk melakukan ini:
Tentukan pemesanan kustom. Manfaat dari solusi ini adalah Anda dapat menggunakan kembali urutan dan memiliki banyak cara untuk mengurutkan instance dari kelas yang sama:
Menjawab pertanyaan Anda Apakah ada fungsi standar yang dimasukkan ke dalam Scala yang dapat melakukan sihir seperti List ((2,1), (1,2)).
Ada sekumpulan urutan yang sudah ditentukan sebelumnya , misalnya untuk String, tupel hingga 9 arity dan seterusnya.
Tidak ada hal seperti itu untuk kelas kasus, karena itu bukan hal yang mudah untuk diluncurkan, mengingat nama bidang tidak dikenal secara a-priori (setidaknya tanpa sihir makro) dan Anda tidak dapat mengakses bidang kelas kasus dengan cara lain selain dengan nama / menggunakan iterator produk.
sumber
The
unapply
metode dari objek pendamping menyediakan konversi dari kasus kelas Anda keOption[Tuple]
, di manaTuple
adalah tuple sesuai dengan daftar argumen pertama dari kelas kasus. Dengan kata lain:sumber
Metode sortBy akan menjadi salah satu cara umum untuk melakukan ini, misalnya (urutkan di
tag
lapangan):sumber
l.sortBy( e => e._tag + " " + e._load + " " + ... )
?sortBy
, maka ya, baik itu, atau tambahkan / gunakan fungsi yang sesuai untuk / pada kelas (misalnya_.toString
, atau metode kustom atau fungsi eksternal yang signifikan secara leksografis Anda sendiri).List((2,1),(1,2)).sorted
objek kelas kasus? Saya tidak melihat perbedaan besar antara tupel bernama (case class == bernama tuple) dan tupel sederhana.Option[TupleN]
, lalu panggilget
itul.sortBy(A.unapply(_).get)foreach(println)
:, yang menggunakan urutan yang disediakan pada tupel yang sesuai, tetapi ini hanyalah contoh eksplisit dari gagasan umum yang saya berikan di atas .Karena Anda menggunakan kelas kasus, Anda dapat memperluas dengan Ordered seperti ini:
sumber