You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala非Spark环境下键映射后分组并拼接值的高效实现方法

Absolutely! Scala's standard library has you covered with clean, efficient ways to combine key transformation, grouping, and value concatenation. Let's walk through the best approaches, including a one-pass solution that's great for larger datasets.

Approach 1: Intuitive groupBy + Aggregation

This is the most straightforward method, perfect for readability when performance isn't the absolute top priority.

First, let's set up sample data to work with:

val myMap: Map[Int, String] = Map(1 -> "a", 2 -> "b", 3 -> "c", 4 -> "d")
def f(i: Int): String = if (i % 2 == 0) "even" else "odd"

Now, apply the key transformation, group entries, and concatenate values:

// Group by the transformed key, then concatenate all values in each group
val result = myMap
  .groupBy { case (key, _) => f(key) } // Group using the transformed key from function f
  .map { case (groupKey, entries) => groupKey -> entries.values.mkString } // Concatenate values in each group

A quick note: You might see mapValues(_.values.mkString) used as shorthand here, but it returns a lazy view. If you want a strict Map (to avoid re-computing the concatenation later), stick with the full map syntax shown above.

Approach 2: One-Pass foldLeft (More Efficient)

If you're working with a large map and want to minimize overhead (this only traverses the original map once), use foldLeft paired with StringBuilder to avoid unnecessary string copies:

val result = myMap.foldLeft(Map.empty[String, StringBuilder]) {
  case (accumulator, (originalKey, value)) =>
    val newGroupKey = f(originalKey)
    accumulator.get(newGroupKey) match {
      case Some(stringBuilder) =>
        // Append the value to the existing StringBuilder
        stringBuilder.append(value)
        accumulator // No need to re-create the map—StringBuilder handles mutability internally
      case None =>
        // Create a new entry with a fresh StringBuilder initialized to the value
        accumulator + (newGroupKey -> new StringBuilder(value))
    }
}
// Convert all StringBuilders to final String values
.map { case (groupKey, sb) => groupKey -> sb.toString }

This approach runs in O(n) time with minimal intermediate object creation, making it ideal for performance-critical code.

Bonus: Adding Separators

If you need to join values with a separator (like commas), adjust the code accordingly:

  • For the groupBy method: Use entries.values.mkString(", ")
  • For the foldLeft method: Check if the StringBuilder is empty before appending the separator, or use a small helper function to handle edge cases cleanly.

内容的提问来源于stack exchange,提问作者user3685285

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 08:29:18