【问题标题】:Scala: How to multiply a List of Lists by valueScala:如何将列表列表乘以值
【发布时间】:2017-11-15 23:26:34
【问题描述】:

现在正在学习 Scala 并使用列表。想要将数组乘以一个元素(例如 1)。

但是我得到以下错误:

需要标识符,但找到整数常量

当前代码:

def multiply[A](listOfLists:List[List[A]]):List[List[A]] =
if (listOfLists == Nil) Nil
else -1 * listOfLists.head :: multiply(listOfLists.tail) 
val tt = multiply[List[3,4,5,6];List[4,5,6,7,8]]
print(tt);;

【问题讨论】:

  • 你需要理顺语法。在 Scala 中,您必须在方括号中传递 types。您再次尝试使用错误的语法传递 values。你可能想做multiply(List(List(3,4,5,6), List(4,5,6,7,8)))之类的事情。同样在 Scala 中,您通常不需要分号。
  • 你的问题很不清楚。您能否提供一个精确说明您希望发生的事情,包括任何和所有规则、这些规则的例外情况、极端情况、特殊情况、边界情况和边缘情况?您能否提供示例输入和输出来展示您期望发生的情况,无论是在正常情况下,还是在所有异常情况、极端情况、特殊情况、边界情况和边缘情况下?

标签: scala list multiplication


【解决方案1】:

您的代码存在一些问题:

  1. 一般来说,您不能对不受约束的泛型类型执行算术运算;不知何故,您必须传达任何支持的算术运算。
  2. 乘以 1 通常不会产生任何影响。
  3. 如前所述,您不要使用方括号声明 List 实例(它们用于声明泛型类型参数)。
  4. 您传递给 multiply 的参数是两个单独的列表(使用无效的分号分隔符而不是逗号),而不是列表列表。
  5. if 子句中,返回值为Nil,它与声明的返回类型List[List[A]] 匹配。然而,else 子句试图执行一个计算,该计算将List 实例(不是列表的内容)乘以一个 Int。即使这是有道理的,结果类型显然不是List[List[A]]。 (这也让我很难准确理解您要完成的工作。)

假设您尝试将内部列表的每个成员乘以特定因子,以下是更正上述代码的版本:

// Multiply every element in a list of lists by the specified factor, returning the
// resulting list of lists.
//
// Should work for any primitive numeric type (Int, Double, etc.). For custom value types,
// you will need to declare an `implicit val` of type Numeric[YourCustomType] with an
// appropriate implementation of the `Numeric[T]` trait. If in scope, the appropriate
// num value will be identified by the compiler and passed to the function automatically.
def multiply[A](ll: List[List[A]], factor: A)(implicit num: Numeric[A]): List[List[A]] = {

  // Numeric[T] trait defines a times method that we use to perform the multiplication.
  ll.map(_.map(num.times(_, factor)))
}

// Sample use: Multiply every value in the list by 5.
val tt = multiply(List(List(3, 4, 5, 6), List(4, 5, 6, 7, 8)), 5)
println(tt)

这应该会产生以下输出:

List(List(15, 20, 25, 30), List(20, 25, 30, 35, 40))

但是,您可能只是想将列表中的所有值相乘。这实际上更简单一些(注意不同的返回类型):

def multiply[A](ll: List[List[A]])(implicit num: Numeric[A]): A = ll.flatten.product

// Sample use: Multiply all values in all lists together.
val tt = multiply(List(List(3, 4, 5, 6), List(4, 5, 6, 7, 8)))
println(tt)

这应该会产生以下输出:

2419200

我建议你阅读一本关于 Scala 的好书。这些例子中有很多非常复杂的东西,在这里解释它们需要很长时间。 Odersky, Spoon & Venners 的 Programming in Scala, Third Edition 是一个好的开始。这将涵盖List[A] 操作,例如mapflattenproduct 以及implicit 函数参数和implicit val 声明。

【讨论】:

    【解决方案2】:

    要使数字运算可用于键入A,您可以使用context boundAscala.math.Numeric 相关联,这提供了timesfromInt 等方法来执行此使用中的必要乘法案例:

    def multiply[A: Numeric](listOfLists: List[List[A]]): List[List[A]] = {
      val num = implicitly[Numeric[A]]
      import num._
      if (listOfLists == Nil) Nil else
        listOfLists.head.map(times(_, fromInt(-1))) :: multiply(listOfLists.tail) 
    }
    
    multiply( List(List(3, 4, 5, 6), List(4, 5, 6, 7, 8)) )
    // res1: List[List[Int]] = List(List(-3, -4, -5, -6), List(-4, -5, -6, -7, -8))
    
    multiply( List(List(3.0, 4.0), List(5.0, 6.0, 7.0)) )
    // res2: List[List[Double]] = List(List(-3.0, -4.0), List(-5.0, -6.0, -7.0))
    

    有关context bound的更多详细信息,请参阅相关SO link

    【讨论】:

    • 我没有投反对票,但考虑到隐含的 Scala 知识水平,“你需要将 A 限制为上下文绑定,例如 Numeric[A]”对于 OP 来说不太容易理解通过他们的帖子。所以“还没有(那个)有用”。
    • @原型保罗,感谢您的评论。我假设任何编写 Scala 泛型的人都应该最低限度地接触到一些隐式值、上下文边界等概念。尽管如此,我已经稍微修改/扩展了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 2021-07-30
    • 2019-12-30
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 2015-05-17
    相关资源
    最近更新 更多