首页 文章

使用scala计算字符串中的char频率

提问于
浏览
1

我搜索一种从字符串中计算不同字符的方法 . 问题是不允许使用scala-api中的任何函数或使用vars(仅限val) .

我想要那样的结果

val fruit: String = "dasisteintest"
println(fruit.groupBy(identity).mapValues(_.size))
Map(e -> 2, s -> 3, n -> 1, t -> 3, a -> 1, i -> 2, d -> 1)

在我做的每一次尝试中,我最后都有一个 list[(Char,Int)] ,我必须改变Int . 但是因为它改变了它 . 如何实现计数char算法?

4 回答

  • 1

    您可以使用以下代码段:

    val fruit: String = "dasisteintest"
    val map = scala.collection.mutable.HashMap.empty[Char, Int]
    for (symbol <- fruit) {
      if (map.contains(symbol))
        map(symbol) = map(symbol) + 1
      else
        map.+=((symbol, 1))
    }
    println(map)
    
  • 0
    def countChars(str: String) = {
      def loop(chars: List[Char], acc: Map[Char, Int]): Map[Char, Int] = {
        chars match {
          case Nil => acc
          case char :: rest =>
            loop(rest, acc + (char -> (acc(char) + 1)))
        }
      }
    
      loop(str.toList, Map.empty[Char, Int] withDefaultValue 0)
    }
    

    测试:

    @ val fruit: String = "dasisteintest" 
    fruit: String = "dasisteintest"
    @ countChars(fruit) 
    res4: Map[Char, Int] = Map('e' -> 2, 's' -> 3, 'n' -> 1, 't' -> 3, 'a' -> 1, 'i' -> 2, 'd' -> 1)
    

    无论你在这里使用什么,都来自scala api, Map.apply ,或 Map.emptyList.:: . 很难不使用scala api中的任何函数 . 我的猜测是你不应该使用像_417829这样的东西,你应该做一些更低级别的事情 . 折叠在这里是自然的解决方案,比如 foldLeft ,但如果这被认为是"using a function from scala api",你可以自己实现 foldLeft ,就像我在我的解决方案中所做的那样 .

    对于 withDefaultValue ,你可以用显式检查替换它是否存在值,并在那种情况下放1 .

    您不知道如何更改不可变的列表或映射?您只需更改该值即可创建一个新列表 .

    对于 Map ,给出

    val map = Map('a' -> 3)
    

    你可以更新它

    @ map.updated('a', 4) 
    res6: Map[Char, Int] = Map('a' -> 4)
    

    要么

    @ map + ('a' -> 4) 
    res7: Map[Char, Int] = Map('a' -> 4)
    

    两者都完全相同 - 插入或更新 - 并返回新 Map .

    在这里,您可以找到如何更新列表中的元素

    Replace element in List with scala

    虽然你很少想按索引访问列表,但你只需要从旧的列表中构建一个新列表,同时以某种方式迭代它,例如折叠 .

  • 1

    这是预期的代码 . 首先是从列表中返回char的函数

    def removeFromList(l: List[Char], l2: List[Char], toDelete: Char): List[Char] = {
           if (l.isEmpty) l2
           else {
               if (l.head == toDelete)
                  removeFromList(l.tail, l2, toDelete)
               else 
                  removeFromList(l.tail, l2 :+ l.head, toDelete)
           }
        }
    

    然后是计算字符和调用的函数 removeFromList()

    def zaehlZeichen(s: String): List[(Char, Int)] = {
        val sl: List[Char] = s.toUpperCase().toList
        if (sl.isEmpty) Nil
        else {
          val l: List[Char] = List()
          val tupleList: List[(Char, Int)] = List();
          val in: Int = countChar(sl, 0, sl.head)
          val t: List[(Char, Int)] = tupleList :+ (sl.head, in)
          val cutL: List[Char] = removeFromList(sl, l, sl.head)
          t ::: zaehlZeichen(cutL.mkString);
        }
      }
    
  • 0

    “Scala API没有函数”是什么意思?这是否包含来自集合api的函数?如果是这样,那么忽略我的答案 . 但是,如果我们甚至不能使用reduce方法,我看不出这个练习的重点 .

    这就是我想出的:

    val fruit: String = "dasisteintest"
    fruit.foldLeft[Map[Char,Int]](Map.empty)((map, c) => map + (c -> (map.getOrElse(c, 0) + 1)))
    

    虽然你能扩展“你必须改变Int”的意思吗?

相关问题