我最近遇到了这个问题:JPA: How do I sort on a Set field in my entity?
我开始考虑在Scala中可以进行类似的排序
所以我们有一个用户列表。每个用户都有排序的组织列表。我们希望按组织名称列表对这个用户列表进行排序。用户按第一个组织名称排序,当名字相等时,用二等名称进行比较,依此类推
我设法写了这样的排序,但在某些情况下,它给出了错误的结果。
class Organization (aId: Int, aName: String) {
val id:Int = aId
var name:String = aName
}
class User (aId: Int, aOrganizations: List[Organization]) {
val id:Int = aId
var organizations:List[Organization] = aOrganizations
}
val o1 = new Organization(1, "AAA")
val o2 = new Organization(2, "AAAA")
val o3 = new Organization(3, "BBB")
val o4 = new Organization(4, "BBBB")
val o5 = new Organization(5, "CCC")
val o6 = new Organization(6, "AAA BBB")
val u1 = new User(1, List(o1))
val u2 = new User(2, List(o2))
val u3 = new User(3, List(o3))
val u4 = new User(4, List(o4))
val u5 = new User(5, List(o1,o5))
val u6 = new User(6, List(o2,o3))
val u7 = new User(7, List(o3,o4))
val u8 = new User(8, List(o1,o2,o3,o4))
val u9 = new User(9, List(o1,o2,o3,o5))
val u10 = new User(10, List())
val u11 = new User(11, List(o6))
val users = List(u1, u2, u3, u4, u5, u6, u7, u8, u9, u10, u11)
// below line should be improved
val sortedUsers = users.sortWith(_.organizations.foldLeft("")((b,a) => b + a.name + ",") < _.organizations.foldLeft("")((b,a) => b + a.name + ","))
sortedUsers.foreach{ x => print(x.id+" ")}
// received result: 10 11 1 8 9 5 2 6 3 7 4
// expected result: 10 1 8 9 5 11 2 6 3 7 4
如何进行此类排序?
答案 0 :(得分:3)
解决此问题最直接的方法可能是使用sortBy
代替sortWith
。 Scala为Iterable[A]
提供了一个词典排序实例,其中A
有一个排序实例,因此您只需要为Organization
提供一个排序实例:
implicit val organizationOrdering: Ordering[Organization] =
Ordering.by(_.name)
val sortedUsers = users.sortBy(_.organizations.toIterable)
您也可以只为User
提供一个实例,然后使用sorted
:
implicit val organizationOrdering: Ordering[Organization] =
Ordering.by(_.name)
implicit val userOrdering: Ordering[User] =
Ordering.by(_.organizations.toIterable)
val sortedUsers = users.sorted
如果您不想引入这些实例,可以明确传递一个实例:
val sortedUsers = users.sortBy(_.organizations.toIterable)(
Ordering.Iterable(Ordering.by(_.name))
)
遗憾的是,List[A: Ordering]
没有实例,但显然有good reasons for that。