scala如何减少而n> 0

时间:2017-06-09 05:14:47

标签: scala while-loop functional-programming

我想知道是否有办法以更实用的方式处理while(n> 0)循环,我有一个小的Scala应用程序,它计算从1到N的范围内等于K的位数: 例如30和3将返回4 [3,13,23,30]

object NumKCount {

  def main(args: Array[String]): Unit = {        
    println(countK(30,3))
  }

  def countKDigit(n:Int, k:Int):Int = {
      var num = n
      var count = 0
      while (num > 10) {
        val digit = num % 10
        if (digit == k) {count += 1}
        num = num / 10
      }
      if (num == k) {count += 1}                       
      count
  }

  def countK(n:Int, k:Int):Int = {          
    1.to(n).foldLeft(0)((acc, x) => acc + countKDigit(x, k))
  }
}

我正在寻找一种使用纯函数方法定义函数countKDigit的方法

4 个答案:

答案 0 :(得分:2)

首先将数字n扩展为数字序列

def digits(n: Int): Seq[Int] = {
  if (n < 10) Seq(n)
  else digits(n / 10) :+ n % 10
}

然后通过计算k

的出现次数来减少序列
def countKDigit(n:Int, k:Int):Int = {
  digits(n).count(_ == k)
}

或者您可以使用countKDigit

完全避免flatMap
def countK(n:Int, k:Int):Int = {
  1.to(n).flatMap(digits).count(_ == k)
}

答案 1 :(得分:0)

假设K总是1位数,您可以将n转换为String并使用collectfilter,如下所示(功能不多)你可以用Integer)做的事情:

def countKDigit(n: Int, k: Int): Int = {
  n.toString.collect({ case c if c.asDigit == k => true }).size
}

def countKDigit(n: Int, k: Int): Int = {
  n.toString.filter(c => c.asDigit == 3).length
}

E.g。

scala> 343.toString.collect({ case c if c.asDigit == 3 => true }).size
res18: Int = 2

scala> 343.toString.filter(c => c.asDigit == 3).length
res22: Int = 2

答案 2 :(得分:0)

以下方法如何:

scala> val myInt = 346763
myInt: Int = 346763

scala> val target = 3
target: Int = 3

scala> val temp = List.tabulate(math.log10(myInt).toInt + 1)(x => math.pow(10, x).toInt)
temp: List[Int] = List(1, 10, 100, 1000, 10000, 100000)

scala> temp.map(x => myInt / x % 10)
res17: List[Int] = List(3, 6, 7, 6, 4, 3)

scala> temp.count(x => myInt / x % 10 == target)
res18: Int = 2

答案 3 :(得分:0)

计算数字序列中单个数字的出现次数。

def countK(n:Int, k:Int):Int = {
  assert(k >= 0 && k <= 9)
  1.to(n).mkString.count(_ == '0' + k)
}

如果您真的只想将countKDigit()修改为功能更强大的设计,那么总会有递归。

def countKDigit(n:Int, k:Int, acc: Int = 0):Int =
  if (n == 0) acc
  else countKDigit(n/10, k, if (n%10 == k) acc+1 else acc)