32

因此,我正在完成“不耐烦的 Scala”中的一些练习,其中之一是:

编写一个for循环来计算字符串中所有字母的 Unicode 代码的乘积。例如,“你好”中的字符的乘积是 9415087488 L。

下一个问题是做同样的事情,但没有for循环——它暗示我们应该检查StringOpsScaladoc。

我检查了Scaladoc 中的RichCharandStringOps部分,也许我误读或看错了地方,但我找不到任何可以让我匹配他们的输出的东西。到目前为止,我已经尝试过:

scala> x.foldLeft(1)(_ * _.toInt)
res0: Int = 825152896

scala> x.foldLeft(1)(_ * _.getNumericValue)
res5: Int = 2518992

scala> x.foldLeft(1)(_ * _.intValue())
res6: Int = 825152896

scala> var x = 1
x: Int = 1

scala> for (c <- "Hello") x *= c.toInt

scala> x
res12: Int = 825152896

这与他们的输出不匹配。

我如何做到这一点,无论是方式for还是非for方式?

谢谢!

4

10 回答 10

31

当您这样做x.foldLeft(1)(_ * _.toInt)时,结果类型将推断为 an Int,但 9415087488 太大而Int无法存储它。

所以你需要告诉 Scala usingLong来存储它。

scala> val x = "Hello"
x: java.lang.String = Hello

scala> x.foldLeft(1L)(_ * _.toInt)
res1: Long = 9415087488

scala> var x: Long = 1
x: Long = 1

scala> for (c <- "Hello") x *= c.toInt

scala> x
res7: Long = 9415087488
于 2012-06-23T00:18:42.177 回答
13

如果您将 String .toLong 的每个 RichChar 转换,它也可以工作。例如,这个:

str.map (_.toLong).product- 工作正常,没有 foldLeft 或循环

这是循环变体:

def product(str: String): Long = {
    var prod: Long = 1
    for (ch <- str) prod *= ch
    prod
}
于 2013-03-19T18:56:27.627 回答
8

StringOps 中有一个特殊的“产品”方法,它可以将集合的元素相乘。但它使用 Char 类型,因为字符串由 char 元素组成。我们在尝试计算“Hello”.product 时出现溢出。因此,我通过“Hello”.map(_.toLong) 将字符串转换为 Long Unicode 值的向量,并通过以下代码计算其元素的乘积:

scala> "Hello".map(_.toLong).product
res79: Long = 9415087488
于 2015-09-15T11:55:48.807 回答
5

这是另一种方式:

scala> (for (c <- "Hello") yield c.toLong).product
res36: Long = 9415087488
于 2015-03-02T18:31:13.307 回答
3

我发现最直接的方法是:

"Hello".foldLeft(1L)((x:Long, y:Char) => x*y)

该方法接受两个参数:一个 Long 和一个接受 Long 和 Char 并返回 Long 的委托函数。您可以像这样直接传递一个匿名函数,或者您可以在别处定义该函数并传递它,如下所示:

def multiply(x:Long, y:Char) = {
    x*y
}
"Hello".foldLeft(1L)(multiply)
于 2014-04-08T02:34:25.420 回答
2

我认为转换到中间映射效率低下,因为在这种情况下,集合被迭代两次:一次是创建 long 的映射,第二次是乘以所有元素。也不需要龙氏不必要的临时收集。我投票给

"Hello".foldLeft(1L)(_ * _)
于 2016-02-09T14:01:55.980 回答
1

不使用 for 循环所需的练习,所以我已经递归了:

def unicode_rec(s: String): Int = 
  if(s == "") 1 
  else s.head.toInt * unicode_rec(s.tail)
于 2019-02-15T22:49:05.923 回答
0

另一种变体:

"Hello".aggregate(1L)({(prod,ch) => prod * ch.toLong}, {(p1,p2)=>p1*p2})
于 2016-06-15T17:28:10.113 回答
0

所以在这里我们聚在一起:)

    // one way
    val longs = for (c <- str) yield c.toLong
    println(longs.product)

    // 2nd way
    println(str.foldLeft(1L)(_ * _.toInt))

    // 3rd way
    var x = 1L
    for (c <- str) yield x *= c.toInt
    println(x)

    // 4th way
    var product = 1L
    for (c <- str) {
      product *= c.toInt
    }
    println(product)

    // 5th way
    println(str.map(_.toLong).product)

    // 6th way
    println(str.foldLeft(1L)(_ * _))

    // 7th way
    println(str.map(_.toLong).reduceLeft(_ * _)) // my IDE warns `Replace reduce with product` 

    // 8th way
    println(str.map(_.toLong).scanLeft(1L)(_ * _).last)

    // 9th way
    println(str.map(_.toLong).reduce((x, y) => (x * y))) // my IDE warns `Replace reduce with product`

   // using recursion
   def exercise9(str: String): Long = {
    var product = str.head.toLong
    if (str.tail.length > 0) {
        product *= exercise9(str.tail)
    }
    product
  }
于 2020-02-16T11:42:46.843 回答
0

在同一本书上也取得了进展。可能看起来有点像 java 风格,但它确实发挥了作用:

scala> "Hello".map( x => x.toLong).reduce( (a, b) => a * b)
val res45= 9415087488
于 2021-03-02T05:08:54.303 回答