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

时间:2016-05-08 23:40:13

标签: scala

我搜索从字符串中计算不同字符的方法。 问题是不允许使用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算法?

5 个答案:

答案 0 :(得分: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)

答案 1 :(得分:1)

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.applyMap.emptyList.::。很难不使用scala api中的任何函数。我的猜测是你不应该使用像groupBy之类的东西,你应该做一些更低级别的事情。折叠是这里的自然解决方案,例如foldLeft,但是如果考虑使用scala api&#34;中的函数,您可以自己实现foldLeft,就像我在解决方案中所做的那样

对于withDefaultValue,您可以使用显式检查来替换它是否存在值,并在那种情况下放置1。

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

对于地图,给出

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)

两者都完全相同 - 插入或更新 - 并返回新地图。

您可以在此处找到如何更新列表中的元素

Replace element in List with scala

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

答案 2 :(得分: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”的意思吗?

答案 3 :(得分:0)

这是预期的代码。 首先是从列表中返回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);
    }
  }

答案 4 :(得分:0)

object CountEachCharInString 
{
  //Counts the number of a specific character in the Input String
  def characterCount(inputChar: Char, str: String): Unit = 
  {
    var num: Int = 0
    num = str.count(_ == inputChar);
    
/*
    //Implementation of count method
    for(i <- 0 to str.length - 1)
    {
      if(str(i) == inputChar) 
      {
        num += 1
      }
    }
*/
    println(s"$inputChar appears $num times")
  }
  
  
  def countAllChars(inputStr: String): Unit = 
  {
    
    //To eliminate duplicates, need one loop inside the other. str(i) == str(j)
    for(i <- 0 to inputStr.length - 1)
    {
      var occurence: Int = 0
      
      for(j <- 0 to i-1)
      {
        if(inputStr(j) == inputStr(i))
            occurence = occurence + 1
      }
      
      if(occurence == 0)
      {
        characterCount(inputStr(i), inputStr)
        //var num = inputStr.count(_ == inputStr(i))
        //println( inputStr(i) + s" appears $num times")
      }        
    }
  }
  
  
  def main(args: Array[String]): Unit =
  {
    countAllChars("HelloforHello...^^&&&&")
  }
}