【问题标题】:Scala: map just first element in tupleScala:仅映射元组中的第一个元素
【发布时间】:2017-08-24 20:49:12
【问题描述】:

我想在元组上使用一些函数,它返回只有第一个元素转换而其他元素不变的元组。

这是 Tuple2 的幼稚版本:

def mapFirst[T, U, R](tuple: (T, U))(f: T => R): (R, U) = tuple match {
     |   case (x, y) => f(x) -> y
     | }

mapFirst((1, 2))(_ * 5) // returns (5, 2)

虽然感觉不是原生的,但我想要的是这样写:

(1, 2).mapFirst(_ * 5)

然后我写了隐式转换:

class RichTuple[T, U](tuple: (T, U)) {
  def mapFirst[R](f: T => R): (R, U) = tuple match {
    case (x, y) => f(x) -> y
  }
}

implicit def tuple2RichTuple[T, U](tuple: (T, U)): RichTuple[T, U] = new RichTuple(tuple)

(1, 2).mapFirst(_ * 5)

然后,当我只想在 Tuple3 上映射第二个元素或第一个元素时,我将不得不再次编写相同的样板。是否有一些内置了此类方法的库?

【问题讨论】:

  • 可能想要使用 Shapeless 及其 Lenses 实现。

标签: scala tuples


【解决方案1】:

你可以使用无形元组函数:

import shapeless._
import syntax.std.tuple._
val x=(1,2,3)
val y=x.updatedAt(0,x.head*5)
// y= (5,2,3)

【讨论】:

    【解决方案2】:

    您可以使用案例类而不是元组(这是一种很好的风格),然后使用命名元素,例如

    case class Pie(filling: String, weight: Double, servings: Int)
    val p = Pie("cheese", 500.0, 2)
    val q = p.copy(filling = "potato")
    val r = p.copy(weight = 750.0, servings = 3)
    

    【讨论】:

      【解决方案3】:

      我们可以使用 _1 作为元组的字段。另一种解决方案,仅使用标准库:

      val x = (1, 2, 3)
      val y = x.copy(_1 = x._1 * 5)
      

      【讨论】:

        猜你喜欢
        • 2012-05-22
        • 2016-02-10
        • 1970-01-01
        • 2018-05-05
        • 2023-03-06
        • 2013-01-13
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多