2017-06-09 9 views
2

もっと機能的な方法でwhile(n> 0)ループを処理する方法があるのだろうか、私はKに等しい桁数を数える小さなScalaアプリを持っています実施例30および3 4 [3、13、23、30]を返すscala how to reduce while n> 0

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)) 
    } 
} 

Iは純粋に機能的なアプローチを使用して機能countKDigitを定義する方法を探しています:1からNの範囲から

答えて

1

まず桁

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

のシーケンスに数nを展開しk

def countKDigit(n:Int, k:Int):Int = { 
    digits(n).count(_ == k) 
} 

それとも、flatMap

を使用して、完全に countKDigitを避けることができるの発生をカウントすることにより、シーケンスを減らします
def countK(n:Int, k:Int):Int = { 
    1.to(n).flatMap(digits).count(_ == k) 
} 
0

Kは常に1桁、あなたがStringnを変換して使用することができていると仮定するとcollectまたはfilter

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 
} 

例えば:、以下のように(あなたがIntegerで行うことができます多くの機能のものがありません)以下のアプローチについて

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 
+1

'filter(c => c.asDigit == k).length'を' count(_。asDigit == k) 'に置き換えることができます。 –

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 
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)