scala zip list to tuple

孤人 提交于 2019-12-14 04:17:13

问题


Working with JodaTime, trying to convert a List[LocalDate] to Tuple2[JodaTime, JodaTime] so I can do multi-assigment like so:

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

which of course does not compile. Is there a similarly concise way to do the above? I know I can just do it manually:

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

but that's a bit ugly


回答1:


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



回答2:


What you want (assuming you don't want to go the conversion-to-Seq route) is Scalaz's Bifunctor instance for tuples (which isn't in the standard library). With it you can write the following:

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)

Or, in your case:

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



回答3:


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

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



回答4:


If you want to keep the type safety of using a tuple (remember, when unapplying a Seq, the compiler will not check the length), you can write a wrapper to add a function not available in the standard library, which will let you map over a tuple.

In the case of mapping over both elements using a single function, because a Tuple2[A, B] has two type parameters, the key to making this work is to require evidence that A and B are the same type. To do this, require an implicit parameter of type B =:= A; if the types are indeed equal, the compiler will supply a function of type 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)

This could be done in a more general and useful way (applicable to more types than just Tuple2), if implemented in terms of Scalaz's Bifunctor trait.



来源:https://stackoverflow.com/questions/11363584/scala-zip-list-to-tuple

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!