分组与排序
groupBy 与 sortBy
分组与排序 是 CoddyKit 上的免费 Scala for Backend Engineering & Functional Programming 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Scala for Backend Engineering & Functional Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
组织数据
现实世界的数据通常需要根据某个属性进行分组,或根据某个键进行排序。Scala 集合提供了 groupBy、sortBy、sortWith 等操作,以声明式方式完成这些任务。
object Main {
def main(args: Array[String]): Unit = {
val nums = List(5, 3, 8, 1, 9, 2)
println(nums.sorted)
}
}sorted:自然顺序
sorted 按元素的自然顺序排序(数字按升序排列,字符串按字母顺序排列)。它需要一个排序规则,而常见类型通常都提供了相应规则。
object Main {
def main(args: Array[String]): Unit = {
println(List(3, 1, 2).sorted)
println(List("pear", "apple", "fig").sorted)
}
}sortBy:按键排序
sortBy 根据从每个元素中派生出的值进行排序。请提供一个用于提取排序键的函数。
object Main {
def main(args: Array[String]): Unit = {
val words = List("banana", "fig", "apple")
val byLength = words.sortBy(_.length)
println(byLength)
}
}按降序排序
要按降序排序,可以对数值键取负值,或使用 sorted(Ordering.Int.reverse)。对于派生键,使用带减号的 sortBy 更为简洁。
object Main {
def main(args: Array[String]): Unit = {
val nums = List(5, 3, 8, 1)
println(nums.sortBy(-_))
println(nums.sorted(Ordering.Int.reverse))
}
}sortWith:自定义比较器
sortWith 接收一个函数:当第一个参数应排在第二个参数之前时返回 true,从而让您完全控制排序顺序。
object Main {
def main(args: Array[String]): Unit = {
val nums = List(5, 3, 8, 1)
val descending = nums.sortWith((a, b) => a > b)
println(descending)
}
}按多个键排序
sortBy 可以返回一个元组,从而同时根据多个键排序:它先比较第一个元素,再用第二个元素打破平局。
object Main {
def main(args: Array[String]): Unit = {
val people = List(("Ann", 30), ("Bob", 25), ("Ann", 22))
val sorted = people.sortBy { case (name, age) => (name, age) }
println(sorted)
}
}groupBy:分区到 Map 中
groupBy 返回一个 Map:每个键都是您的函数返回的结果,每个值则是共享该键的元素列表。
object Main {
def main(args: Array[String]): Unit = {
val nums = List(1, 2, 3, 4, 5, 6)
val byParity = nums.groupBy(_ % 2 == 0)
println(byParity)
}
}按计算出的键分组
分组键可以是任何内容:首字母、长度或类别。每个不同的键都会成为一个分组。
object Main {
def main(args: Array[String]): Unit = {
val words = List("apple", "avocado", "banana", "cherry", "cranberry")
val byFirstLetter = words.groupBy(_.head)
byFirstLetter.foreach { case (letter, ws) => println(s"$letter -> $ws") }
}
}转换分组
分组后,您通常需要概括每个分组。可以使用 view.mapValues(或 map)转换各组的值,例如统计每组的元素数量。
object Main {
def main(args: Array[String]): Unit = {
val words = List("cat", "car", "dog", "deer", "cow")
val counts = words.groupBy(_.head).view.mapValues(_.size).toMap
println(counts)
}
}一步完成 groupMapReduce
groupMapReduce 会在一次遍历中完成分组、映射每个元素以及归约每组的值。这是一种简洁的方式,可用于构建每个类别的总和等汇总结果。
object Main {
def main(args: Array[String]): Unit = {
val sales = List(("books", 10), ("toys", 5), ("books", 7), ("toys", 3))
val totals = sales.groupMapReduce(_._1)(_._2)(_ + _)
println(totals)
}
}结合分组与排序
一种常见模式是:先将数据分组,再概括每组,最后对汇总结果排序。这里我们统计每个首字母对应的单词数量,并按数量排序。
object Main {
def main(args: Array[String]): Unit = {
val words = List("apple", "avocado", "banana", "cherry", "cranberry", "apricot")
val ranked = words
.groupBy(_.head)
.view.mapValues(_.size).toList
.sortBy(-_._2)
println(ranked)
}
}快速检查
List(1,2,3,4).groupBy(_ % 2 == 0) 会返回什么?
回顾
您学习了分组和排序:
sorted— 自然顺序sortBy— 按派生键排序(使用元组实现多键排序)sortWith— 自定义比较器groupBy— 分区到包含各个分组的Map中groupMapReduce— 在一次遍历中完成分组、映射和归约
常见问题解答
「分组与排序」课时是免费的吗?
是的 — 「分组与排序」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Scala for Backend Engineering & Functional Programming 课程的其余内容,请升级到 CoddyKit PRO。 Scala for Backend Engineering & Functional Programming 课程共包含 4 节课。
「分组与排序」这节课中我会学到什么?
groupBy 与 sortBy 你通过在浏览器中直接运行的动手代码来练习 Scala for Backend Engineering & Functional Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Scala for Backend Engineering & Functional Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Scala for Backend Engineering & Functional Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「分组与排序」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Scala for Backend Engineering & Functional Programming 课中编写并运行代码吗?
能。每节 Scala for Backend Engineering & Functional Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。