操纵元组

时间:2011-08-20 05:16:50

标签: scala tuples

有没有办法在不使用临时变量和启动新语句的情况下操作元组的多个值?

假设我有一个返回元组的方法,我想对这些内联值做一些事情。

e.g。如果我想在某个点拆分一个字符串并反转这些部分

def backToFront(s: String, n:Int) = s.splitAt(n)...

我能做到

val (a, b) = s.splitAt(n)
b + a 

(需要临时变量和新语句)或

List(s.splitAt(n)).map(i => i._2 + i._1).head

(工作,但似乎有点脏,为此创建一个单独的元素列表)或

s.splitAt(n).swap.productIterator.mkString

(适用于这个特定的例子,但只是因为碰巧有swap方法可以做我想要的,所以它不是很通用)。

元组上的zipped方法似乎只适用于列表元组。

另一个例子是,如何在一个语句中将元组('a, 'b, 'c)转换为('b, 'a, 'c)

4 个答案:

答案 0 :(得分:9)

元组只是方便的返回类型,并且不会假设您将使用它进行复杂的操作。在scala论坛上也有类似的discussion

关于最后一个例子,找不到比模式匹配更好的东西。

('a, 'b, 'c) match { case (a, b, c) => (b, a ,c) }

答案 1 :(得分:7)

不幸的是,元组的内置方法是pretty limited

也许你想在你的个人图书馆里找到类似这样的东西,

def fold2[A, B, C](x: (A, B))(f: (A, B) => C): C = f(x._1, x._2)
def fold3[A, B, C, D](x: (A, B, C))(f: (A, B, C) => D): D = f(x._1, x._2, x._3)

通过适当的隐式转换,您可以这样做,

scala> "hello world".splitAt(5).swap.fold(_ + _)
res1: java.lang.String = " worldhello"

scala> (1, 2, 3).fold((a, b, c) => (b, c, a))
res2: (Int, Int, Int) = (2,3,1)

最后一个表达式的替代方法是“管道”运算符|>(从Scalaz或here获取),

scala> ('a, 'b, 'c) |> (t => (t._2, t._3, t._1))
res3: (Symbol, Symbol, Symbol) = ('b,'c,'a)

如果不是必需的注释,这将是很好的,

scala> ("hello ", "world") |> (((_: String) + (_: String)).tupled)
res4: java.lang.String = hello world

答案 2 :(得分:2)

这个怎么样?

s.splitAt(n) |> Function.tupled(_ + _)

[编辑:刚刚注意到你的功能论点是相反的。在这种情况下,您将不得不放弃占位符语法,而是转到:s.splitAt(n) |> Function.tupled((a, b) => b + a)]

对于你的上一个例子,想不出比模式匹配更好的东西(如@ 4e6所示。)

答案 3 :(得分:0)

使用shapeless的当前开发版本,您可以在不解压缩元组的情况下实现此目的:

import shapeless.syntax.std.tuple._

val s = "abcdefgh"
val n = 3

s.splitAt(n).rotateRight[shapeless.Nat._1].mkString("", "", "") // "defghabc"

我认为在最后一行的方法语法被清理之前你不应该等待太久(我说的几天),你可以简单地写一下

s.splitAt(n).rotateRight(1).mkString