Scala 基于集合的多任务分配

Scala 基于集合的多任务分配,scala,collections,tuples,Scala,Collections,Tuples,编辑 最初的问题是“集合到元组”,因为我假设我需要一个元组来执行变量多重赋值。事实证明,可以直接对集合执行变量多重赋值。相应地重新命名该问题 原创 有一个简单的Seq[String]派生自正则表达式,我想将其转换为元组 最直接的方法是什么 我目前有: val(clazz, date) = captures match { case x: Seq[String] => (x(0), x(1)) } 这是可以的,但我的路由层有一堆正则表达式匹配的路由,我将对它们执行val(a、b、c)多

编辑

最初的问题是“集合到元组”,因为我假设我需要一个元组来执行变量多重赋值。事实证明,可以直接对集合执行变量多重赋值。相应地重新命名该问题

原创 有一个简单的Seq[String]派生自正则表达式,我想将其转换为元组

最直接的方法是什么

我目前有:

val(clazz, date) = captures match {
  case x: Seq[String] => (x(0), x(1))
}
这是可以的,但我的路由层有一堆正则表达式匹配的路由,我将对它们执行val(a、b、c)多重分配(捕获组总是已知的,因为如果正则表达式不匹配,则不会处理路由)。最好有一个比match{case..=>}更精简的解决方案


在Scala中将集合转换为元组的最短单行程序是什么?

您可以使用Scalaz中的
|>
操作符使它稍微好一点

scala> val captures = Vector("Hello", "World")
captures: scala.collection.immutable.Vector[java.lang.String] = Vector(Hello, World)

scala> val (a, b) = captures |> { x => (x(0), x(1)) }
a: java.lang.String = Hello
b: java.lang.String = World
如果您不想使用Scalaz,您可以自己定义
|>
,如下所示:

scala> class AW[A](a: A) {
     |   def |>[B](f: A => B): B = f(a)
     | }
defined class AW

scala> implicit def aW[A](a: A): AW[A] = new AW(a)
aW: [A](a: A)AW[A]
scala> val S = Seq
S: scala.collection.Seq.type = scala.collection.Seq$@157e63a

scala> val S(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World
编辑:

或者,类似于@ziggystar的建议:

scala> val Vector(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World
您可以使其更加简洁,如下所示:

scala> class AW[A](a: A) {
     |   def |>[B](f: A => B): B = f(a)
     | }
defined class AW

scala> implicit def aW[A](a: A): AW[A] = new AW(a)
aW: [A](a: A)AW[A]
scala> val S = Seq
S: scala.collection.Seq.type = scala.collection.Seq$@157e63a

scala> val S(a, b) = captures
a: java.lang.String = Hello
b: java.lang.String = World

根据@ziggystar在评论中的建议,您可以执行以下操作:

val (clazz, date) = { val a::b::_ = capture; (a, b)} 


如果在确定列表类型之前验证了它,请注意
Seq
的长度,因为即使列表大小为0或1,代码也会运行

这不是问题的答案,但可能会以不同的方式解决问题


你知道你可以像这样匹配一个
xs:List[String]

val a :: b :: c :: _ = xs 
这会将列表的前三个元素分配给
a、b、c
?您可以在
val
声明中匹配其他内容,如
Seq
,就像在
case
语句中一样。请确保注意匹配错误:


您的问题最初是关于在正则表达式中分配单个捕获组的,它已经允许您直接从它们分配:

scala> val regex = """(\d*)-(\d*)-(\d*)""".r
regex: scala.util.matching.Regex = (\d*)-(\d*)-(\d*)

scala> val regex(a, b, c) = "29-1-2012"
d: String = 29
m: String = 1
y: String = 2012
显然,您也可以在案例中使用这些:

scala> "29-1-2012" match { case regex(d, m, y) => (y, m, d) }
res16: (String, String, String) = (2012,1,29)
然后根据需要对它们进行分组。

Seqs到tuple 要从
序列执行多重赋值,请执行以下操作

val Seq(clazz, date) = captures
如您所见,无需限制为
List
s;如果长度不匹配,此代码将抛出一个
MatchError
(在您的情况下,这很好,因为这意味着您犯了错误)。然后您可以添加

(clazz, date)
重新创建元组

匹配的元组
然而,Jed Wesley Smith发布了一个解决方案,它避免了这个问题,并更好地解决了原始问题。特别是,在您的解决方案中,您有一个未指定长度的Seq,因此如果您犯了错误,编译器不会告诉您;改用元组,编译器可以帮助您(即使它不能对照regexp进行检查)。

对我来说,主要问题是不同的元组具有不同的类型,因此我不知道您是否可以使用返回不同大小元组的函数。此外,在您的示例中,
match
中应该始终有一个转义格,为了避免出现问题,您还应该注意
Seq
可以是长度
您知道可以匹配
xs:List[String]
像这样:
val a::b::c::=xs
要获取列表的前三个元素?@Chris,除非正则表达式匹配,否则路径是不匹配的,所以我总是知道集合的长度。此外,集合类型始终为string类型。我可以做“val(a,b)=(捕获(0),捕获(1))”,但我正在寻找更多的东西generalized@ziggystar,+1不知道,非常直接的解决方案;-)@ziggystar,+1。在看到你的建议后,我的回答感觉有点愚蠢。嗯,我也可以做“val(a,b)=捕获匹配{case x=>(x(0),x(1))}”,没有任何魔力。保存几个字符并不能证明完全使用FP是正确的,在本例中,我使用@ziggystar的简单性;-)不是Ruby或Groovy无法追踪的魔力,而是复杂性/必须摸索意图方面的魔力。要打入钉子(解决问题),在可能的情况下,使用锤子(内置语言功能),然后再使用螺丝刀(FP)。+1,是的,这是一个非常非常好的解决此特定问题的方法。假设这需要Scalaz?对于斯卡拉来说,老实说,托尼·莫里斯静脉的FP方法在这一点上对我来说完全是莫名其妙的。在某一点上,我会看到FP光,但现在我主要关注Scala本身。说到这里,我希望2.10和反思很快就会到来!否则,我将别无选择,只能深入Scalaz以验证这些无反射的案例类。@virtualeyes,我厌倦了人们在所有错误的地方贴上“复杂”标签。在使用该词之前,您是否试图理解
|>
?它只是一个函数应用程序,但从右到左。换句话说,
f(x)
=
x |>f
。为什么是那个方向?因为它有助于类型推断。在这种情况下,使用从左到右的方向时,必须指定函数参数类型。i、 e.
val(a,b)=((x:Vector[String])=>(x(0),x(1))(捕获)
@virtualeyes,编辑没有使用任何Scalaz的东西。顺便说一句,为什么不直接做
val clazz::date::=捕获
?更直接地说,我会按照@ziggystar的建议再次做,“val clazz::date=captures”,集合的长度和类型是已知的,除非正则表达式本身匹配,否则路径是不匹配的。我错过了它,很抱歉,我没有很好地理解@ziggystar的建议,所以我认为我的解决方案会改进它,但它没有。编辑:我的答案提供了一个元组,现在我记得我为什么写它:-)我喜欢大家叫他“@”ziggystar:)对,可以手动处理捕获(0),捕获(1);更喜欢ziggystar的解决方案……它不是问题的“答案”,而是问题的“答案”question@virtualeyes它不会将集合转换为元组。那些以后将要离开的人