我正在浏览并发现了一个关于将String
按字符分组的问题,例如:
输入:
"aaabbbccccdd"
会产生以下输出:
"aaa"
"bbb"
"cccc"
"ddd"
我找到了这个建议:
val str = "aaabbbccccdd"[
val list = str.groupBy(identity).toList.sortBy(_._1).map(_._2)
这位identity
老乡让我很好奇。我发现它在PreDef
中定义如下:
identity[A](x: A): A
所以基本上它会返回给出的任何东西,对吧?但这对groupBy
的调用有何影响?
如果这是一个基本问题,我很抱歉,只是功能性编程仍然在纠缠我的大脑。如果有任何可以让我更清楚的信息,请告诉我
答案 0 :(得分:10)
要理解这一点,只需使用-Xprint:typer
选项调用scala repl:
val res2: immutable.Map[Char,String] = augmentString(str).groupBy[Char]({
((x: Char) => identity[Char](x))
});
Scalac将简单的String
转换为StringOps
,其中TraversableLike
的子类具有groupBy
方法:
def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
val m = mutable.Map.empty[K, Builder[A, Repr]]
for (elem <- this) {
val key = f(elem)
val bldr = m.getOrElseUpdate(key, newBuilder)
bldr += elem
}
val b = immutable.Map.newBuilder[K, Repr]
for ((k, v) <- m)
b += ((k, v.result))
b.result
}
因此groupBy包含一个映射,插入字符按标识函数返回。
答案 1 :(得分:9)
这是你的表达:
val list = str.groupBy(identity).toList.sortBy(_._1).map(_._2)
让我们逐个功能逐项。第一个是groupBy,它将使用鉴别器函数传递的键列表对您的String进行分区,在您的情况下,它是标识符。鉴别器功能将应用于屏幕中的每个字符,并且返回相同结果的所有字符将组合在一起。如果我们想将字母a与其余字母分开,我们可以使用x => x == 'a'
作为我们的鉴别器函数。这会将你的字符串字符分组到map中的函数返回(true或false):
Map(false -> bbbccccdd, true -> aaa)
使用identity
,这是一种“好”的方式来说x => x
,我们会得到一张地图,其中每个字符在地图中分开,在您的情况下:
Map(c -> cccc, a -> aaa, d -> dd, b -> bbb)
然后我们将地图转换为带有(char,String)
的元组toList
列表。
使用sortBy
按字母排序,只需保留字符串,map
即可获得最终结果。
答案 2 :(得分:4)
首先,让我们看看迭代字符串时会发生什么:
scala> "asdf".toList
res1: List[Char] = List(a, s, d, f)
接下来,考虑有时我们希望根据对象的某些特定属性对元素进行分组。
例如,我们可以按照长度分组字符串列表,如...
List("aa", "bbb", "bb", "bbb").groupBy(_.length)
如果您只想按项目本身对每个项目进行分组,该怎么办?您可以传递身份函数,如下所示:
List("aa", "bbb", "bb", "bbb").groupBy(identity)
你可以做一些像这样的傻事,但这很愚蠢:
List("aa", "bbb", "bb", "bbb").groupBy(_.toString)
答案 3 :(得分:1)
看看
str.groupBy(identity)
返回
scala.collection.immutable.Map[Char,String] = Map(b -> bbb, d -> dd, a -> aaa, c -> cccc)
因此元素分组的关键是字符。
答案 4 :(得分:1)
每当您尝试在String上使用groupBy
等方法时。重要的是要注意它隐式转换为StringOps
和不 List[Char]
。
groupBy
的签名由 -
def groupBy[K](f: (Char) ⇒ K): Map[K, String]
因此,结果的形式为 -
Map[Char,String]
groupBy
的签名由 -
def groupBy[K](f: (Char) ⇒ K): Map[K, List[Char]]
如果它已隐式转换为List[Char]
,则结果将为 -
Map[Char,List[Char]]
现在这应该隐含地回答你的好奇问题,就像scala在groupBy
Char
上找到Map[Char, String]
(见签名)然后给你{{1}}。
答案 5 :(得分:0)
基本上list.groupBy(identity)只是说list.groupBy(x => x)的一种奇特方式,在我看来,这更清晰。它将包含重复项目的列表按这些项目分组。