我正在尝试在函数式编程中创建一个函数,该函数接收一个正常的Int值,并将其转换为金融中文数字并返回一个字符串,用于exaple: 301 =三百零一。首先,我有两张地图,一张的数字从0到9,另一张有指数,从10到1000000。
val digits: Map[Int, String] = Map(0 -> "〇", 1 -> "壹", 2 -> "貳", 3 -> "參", 4 -> "肆", 5 -> "伍", 6 -> "陸", 7 -> "柒", 8 -> "捌", 9 -> "玖");
val exponent: Map[Int, String] = Map(1 -> "", 10 -> "拾", 100 -> "佰", 1000 -> "仟", 10000 -> "萬", 100000 -> "億", 1000000 -> "兆");
对于那些不知道的人,这里有一些关于中国数字是如何工作的解释。如果你已经知道了,不要费心读这一段。在中文数字中,当你想要写一个大的数字,例如5000,你写5和1000个符号(伍仟)来表示你在乘以5* 1000。如果你有539,它是5_100 + 3_10 + 9,这将是伍佰參拾玖。最后,如果数字在乘法之间有0‘s,那么不管它们是多少,在其他字符之间只写一个0。例如: 501 = 5_100 + 1,这是伍佰0壹。最后一个例子是: 50103 = 5_10000 + 1*100 + 3,这是伍萬0壹佰0參。
所以我能做的是:
def format(unit: Int): String = {
val l = unit.toString.map(_.asDigit).toList
if(l.isEmpty) ""
else if(l.tail.isEmpty) digits(l.head)
else digits(l.head) + format(l.tail.mkString.toInt)
}这是一个接一个地翻译字符。例如:
format(135) "壹參伍"我不知道怎么继续下去。
发布于 2020-10-22 16:18:20
如果我正确理解了你的问题,你可以这样做:
def toChineseFinancial(number: Int): String = {
val digits = number.toString.iterator.map(_.asDigit).toList
val length = digits.length
val exponents = List.tabulate(length)(n => math.pow(10, n).toInt)
val (sb, _) =
digits
.iterator
.zip(exponents.reverseIterator)
.foldLeft(new collection.mutable.StringBuilder(length * 2) -> false) {
case ((sb, flag), (digit, exp)) =>
if (digit == 0) sb -> true
else if (flag) sb.append("〇").append(digitsMap(digit)).append(exponentsMap(exp)) -> false
else sb.append(digitsMap(digit)).append(exponentsMap(exp)) -> false
}
sb.result()
}您可以看到它运行这里。
注意:我使用mutable.StringBuilder是因为构建Strings有点昂贵,但是如果您想避免任何类型的可更改性,您可以轻松地用一个普通的字符串替换它。
发布于 2020-10-23 06:19:20
我将使用一个简单的exponents映射来扩展它的值,包括:
如下所示:
case class CNU(unit: String, factor: Int)
val exponents: Map[Long, CNU] = Map(
1L -> CNU("", 1),
10L -> CNU("拾", 1),
100L -> CNU("佰", 1),
1000L -> CNU("仟", 1),
10000L ->CNU("萬", 1),
100000L -> CNU("萬", 10),
1000000L -> CNU("萬", 100),
10000000L -> CNU("萬", 1000),
100000000L -> CNU("億", 1),
1000000000L -> CNU("億", 10),
10000000000L -> CNU("億", 100),
100000000000L -> CNU("億", 1000),
1000000000000L -> CNU("兆", 1),
10000000000000L -> CNU("兆", 10),
100000000000000L -> CNU("兆", 100),
1000000000000000L -> CNU("兆", 1000)
)创建方法:
val digits: Map[Int, String] = Map(
0 -> "〇", 1 -> "壹", 2 -> "貳", 3 -> "參", 4 -> "肆",
5 -> "伍", 6 -> "陸", 7 -> "柒", 8 -> "捌", 9 -> "玖"
)
def toChineseNumber(num: Long): String = {
val s = num.toString
val ds = s.map(_.asDigit).zip(s.length-1 to 0 by -1)
ds.foldRight(List.empty[String], 0){ case ((d, i), (accList, dPrev)) =>
val cnu = exponents(math.pow(10, i).toLong)
val digit =
if (d == 0) {
if (dPrev != 0 || num == 0) digits(d) else ""
}
else
digits(d)
val unit =
if (d == 0)
""
else {
if (cnu.factor == 1) cnu.unit else exponents(cnu.factor).unit
}
((digit + unit) :: accList, d)
}.
_1.mkString
}注意,foldRight方法用于从右到左遍历和处理输入数字,元组累加器中的dPrev用于在迭代中携带数字,以处理重复的0's。
测试它:
toChineseNumber(50)
// res1: String = 伍拾
toChineseNumber(30001)
// res2: String = 參萬〇壹
toChineseNumber(1023405)
// res3: String = 壹佰〇貳萬參仟肆佰〇伍
toChineseNumber(2233007788L)
// res4: String = 貳拾貳億參仟參佰〇柒仟柒佰捌拾捌https://stackoverflow.com/questions/64485015
复制相似问题