scala zip list to tuple

时间:2012-07-06 13:53:50

标签: list scala zip tuples variable-assignment

使用JodaTime,尝试将List [LocalDate]转换为Tuple2 [JodaTime,JodaTime],这样我可以像这样进行多重分配:

val(expire, now) = 
  List(row.expireDate, new JodaDate) zip (_.toDateTimeAtStartOfDay.getMillis)

当然不编译。是否有类似简洁的方法来做上述事情?我知道我可以手动完成:

val(expire, now) = 
  (row.expireDate.toDateTimeAtStartOfDay.getMillis, 
   new JodaDate().toDateTimeAtStartOfDay.getMillis)

但这有点难看

4 个答案:

答案 0 :(得分:10)

val Seq(expire, now) = 
  Seq(row.expireDate, new JodaDate).map(_.toDateTimeAtStartOfDay.getMillis)

答案 1 :(得分:4)

对于元组(不在标准库中),您想要的(假设您不想转换到 - Seq路由)是Scalaz's Bifunctor instance。有了它,您可以写下以下内容:

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> val cap = (_: String).toUpperCase
cap: String => java.lang.String = <function1>

scala> val removeLs = (_: String).replaceAll("l", "")
removeLs: String => java.lang.String = <function1>

scala> cap <-: ("hello", "world") :-> removeLs
res0: (java.lang.String, java.lang.String) = (HELLO,word)

或者,在您的情况下:

val f = (_: JodaDate).toDateTimeAtStartOfDay.getMillis
val (expire, now) = f <-: (row.expireDate, new JodaDate) :-> f

答案 2 :(得分:2)

val Seq(a, b) =
  Seq("a", "b").map(_.toUpperCase)

println("a, b = %s, %s".format(a, b)) // a, b = A, B

答案 3 :(得分:1)

如果你想保持使用元组的类型安全(记住,当取消应用Seq时,编译器将不检查长度),你可以编写一个包装器来添加标准中没有的函数库,它可以让你映射一个元组。

如果使用单个函数映射两个元素,因为Tuple2[A, B]有两个类型参数,使这项工作的关键是要求AB的证据是相同的类型。为此,需要一个B =:= A类型的隐式参数;如果类型确实相等,编译器将提供类型为B => A的函数。

class Tuple2Wrapper[A, B](t: (A, B)) {
  def bimap[C, D](f: A => C, g: B => D): (C, D) = (f(t._1), g(t._2))
  def <-:->[C](f: A => C)(implicit ev: B =:= A): (C, C) = bimap(f, f compose ev)
}

implicit def tuple2Tuple2Wrapper[A, B](t: (A, B)) = new Tuple2Wrapper(t)

scala> (1, 1) <-:-> (_ + 1)
res1: (Int, Int) = (2,2)

如果按照Scalaz的Tuple2特征实现,可以采用更通用,更有用的方式(仅适用于Bifunctor以外的更多类型)。