Scala Group是否保留了插入顺序?

Vin*_*ele 28 collections scala hashmap map

Lists,Maps等中的groupBy方法在函数后生成Map.

有没有办法使用groupBy生成一个保留插入顺序的Map(例如LinkedHashMap)?

我正在使用for循环手动插入,但我想知道一个有用的已定义函数是否可以帮助我.

提前致谢.

Lui*_*hys 21

groupBy如定义TraversableLike生成一个immutable.Map,所以你不能使这个方法产生别的东西.

已保留每个条目中元素的顺序,但不保留键的顺序.键是提供的功能的结果,因此它们实际上没有订单.

如果您想根据特定键的第一次出现进行订单,请参阅下面的草图,了解如何执行此操作.假设我们想要按值/ 2对整数进行分组:

val m = List(4, 0, 5, 1, 2, 6, 3).zipWithIndex groupBy (_._1 / 2)
val lhm = LinkedHashMap(m.toSeq sortBy (_._2.head._2): _*)
lhm mapValues (_ map (_._1))
// Map(2 -> List(4, 5), 0 -> List(0, 1), 1 -> List(2, 3), 3 -> List(6))
// Note order of keys is same as first occurrence in original list
Run Code Online (Sandbox Code Playgroud)

  • "每个条目中元素的顺序已经保留",这有保证吗?它在API文档中似乎没有多说. (4认同)
  • @Mortimer如果API文档没有这么说,那么我认为理论上并不能保证(尽管文档一般都很差).元素的顺序只对`Seq`s有意义,而这个方法在所有`Traversable'上都是通用的,但由于实现使用for-expression来遍历元素,所以对于`Seq`s来说它总是如此. . (2认同)
  • 大多数涉及元组的例子最难阅读和理解,包括这个例子。我投了赞成票,因为它有效:) (2认同)

Lei*_*and 19

以下内容将为您提供groupByOrdered一种行为方式.

import collection.mutable.{LinkedHashMap, LinkedHashSet, Map => MutableMap}

object GroupByOrderedImplicit {
  implicit class GroupByOrderedImplicitImpl[A](val t: Traversable[A]) extends AnyVal {
    def groupByOrdered[K](f: A => K): MutableMap[K, LinkedHashSet[A]] = {
      val map = LinkedHashMap[K,LinkedHashSet[A]]().withDefault(_ => LinkedHashSet[A]())
      for (i <- t) {
        val key = f(i)
        map(key) = map(key) + i
      }
      map
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

当我使用该代码时:

import GroupByOrderedImplicit._
0.to(100).groupByOrdered(_ % 10).foreach(println)
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

(0,Set(0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100))
(1,Set(1, 11, 21, 31, 41, 51, 61, 71, 81, 91))
(2,Set(2, 12, 22, 32, 42, 52, 62, 72, 82, 92))
(3,Set(3, 13, 23, 33, 43, 53, 63, 73, 83, 93))
(4,Set(4, 14, 24, 34, 44, 54, 64, 74, 84, 94))
(5,Set(5, 15, 25, 35, 45, 55, 65, 75, 85, 95))
(6,Set(6, 16, 26, 36, 46, 56, 66, 76, 86, 96))
(7,Set(7, 17, 27, 37, 47, 57, 67, 77, 87, 97))
(8,Set(8, 18, 28, 38, 48, 58, 68, 78, 88, 98))
(9,Set(9, 19, 29, 39, 49, 59, 69, 79, 89, 99))
Run Code Online (Sandbox Code Playgroud)


hra*_*ban 5

这是没有地图的:

def orderedGroupBy[T, P](seq: Traversable[T])(f: T => P): Seq[(P, Traversable[T])] = {
   @tailrec
   def accumulator(seq: Traversable[T], f: T => P, res: List[(P, Traversable[T])]): Seq[(P, Traversable[T])] = seq.headOption match {
     case None => res.reverse
     case Some(h) => {
       val key = f(h)
       val subseq = seq.takeWhile(f(_) == key)
       accumulator(seq.drop(subseq.size), f, (key -> subseq) :: res)
     }
   }
   accumulator(seq, f, Nil)
 }
Run Code Online (Sandbox Code Playgroud)

如果您只需要按顺序访问结果(无随机访问)并且希望避免创建和使用Map对象的开销,那么它可能很有用.注意:我没有将性能与其他选项进行比较,实际上可能会更糟.

编辑:要清楚; 假设您的输入已按组密钥排序.我的用例是SELECT ... ORDER BY.