【问题标题】:Scala type casting of function result函数结果的Scala类型转换
【发布时间】:2015-01-12 12:29:04
【问题描述】:

我是 scala 的新手,无法解决这种类型相关的问题。

试图敲出一个函数,该函数将键值元组列表(键可能是非唯一的)转换为属于使用额外“列”列表选择的特定键的聚合值元组列表。 out 需要有 Array[Array[Any]] 的签名:

例子:

输入:

[("k1", 10), ("k2", 15), ("k1", 18), ("k3", 23), ("k1", 13), ("k2", 1)]

列:

COLUMNS = ["k1", "k2"]

输出:

[[10, 18, 13], [15, 1]]

我的尝试看起来像:

val COLUMNS = Array("k1", "k2")

def convert(result: Array[Tuple2[String, Any]]): Array[Array[Any]] = { 
    val grouped = result.groupBy(cell => cell._1)
    val columns = grouped.mapValues(cell => cell.map(column => column._2))

    val tuples = COLUMNS.map(col => columns.getOrElse(col, Array()))
    return tuples
}

我收到以下错误:

<console>:21: error: type mismatch;
 found   : scala.collection.mutable.ArraySeq[Array[_]]
 required: Array[Array[Any]]
         return tuples

有人可以帮忙吗?注意我最后需要 Array[Array[Any]] 类型... 谢谢。

【问题讨论】:

  • 您描述的输出类型是Array[Array[Any]],而您的示例输出是[(Int, Int, Int), (Int, Int)],可能是Array[Any],但不是Array[Array[Any]],它需要一个额外的数组。你想要的输出是不是更像这样?:[[10, 18, 13], [15, 1]]
  • @Rajit:是的,已在我的原始帖子中修复。

标签: scala


【解决方案1】:

你应该只为空数组明确指定Any,因为这里默认有Nothing类型(我还删除了不必要的返回和非常规的大写锁定,简化的lambda):

val Columns = Array("k1", "k2")

def convert(result: Array[(String, Any)]): Array[Array[Any]] = { 
      val grouped = result.groupBy(_._1)
      val columns = grouped.mapValues(_.map(_._2))
      Columns.map(columns.getOrElse(_, Array[Any]()))
}

scala> convert(Array(("k1", 10), ("k2", 15), ("k1", 18), ("k3", 23), ("k1", 13), ("k2", 1)))
res2: Array[Array[Any]] = Array(Array(10, 18, 13), Array(15, 1))

【讨论】:

    【解决方案2】:

    groupBy是这种工作的关键:

    val kvs = Array(("k1", 10), ("k2", 15), ("k1", 18), ("k3", 23), ("k1", 13), ("k2", 1))
    
    scala> Array("k1", "k2") map kvs.groupBy(_._1) map (_ map (_._2))
    res16: Array[Array[Int]] = Array(Array(10, 18, 13), Array(15, 1))
    

    请注意,我们正在利用Map 可以用作从键到值的函数这一事实。在这种情况下,groupBy 的结果是一个 Map 从键到包含它的元组;我们map Map(将其用作函数)遍历感兴趣的键以获取它们的元组,然后从中提取值。

    如果您所追求的某些键可能根本不存在于输入中,您可以使用withDefaultValue 表示在这种情况下应返回一个空数组:

    scala> Array("k1", "k2", "k9") map (kvs.groupBy(_._1) withDefaultValue Array()) map (_ map (_._2))
    res17: Array[Array[Int]] = Array(Array(10, 18, 13), Array(15, 1), Array())
    

    生成的类型将尽可能具体,这可能是您想要的。但是当然,如​​果你想扩大它,你可以通过类型归属来做到这一点,或者简单地通过更广泛的类型声明接收结果的变量。

    【讨论】:

    猜你喜欢
    • 2017-02-19
    • 1970-01-01
    • 2017-01-01
    • 2011-10-07
    • 1970-01-01
    • 1970-01-01
    • 2015-03-17
    • 2021-01-15
    • 2020-06-16
    相关资源
    最近更新 更多