2011-08-20 77 views
7

有没有一种方法来操作元组的多个值而不使用临时变量并启动新的语句?操作元组

说我有一个方法返回一个元组,我想用这些值内联做一些事情。

例如如果我想在某一个点来分割字符串和反向件

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)

回答

9

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

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

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

模式匹配很好! 's.splitAt(n)match {case(a,b)=> b + a}'适用于第一部分 –

+2

可惜标准库中没有'fold'方法;那么你可以's.splitAt(n).fold((a,b)=> b + a)',它也会更有效率。 (是的,当然我自己做了。) –

+0

折叠是一个很好的名字。我更新了我的答案。 –

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) 

最后表达另一种方法是在“管“运营商|>(从斯卡拉兹获得或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

这个怎么样?

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

[编辑:刚才注意到你的函数参数是相反的。在这种情况下,你将不得不放弃占位符语法,而是去为:(如图@ 4E6)s.splitAt(n) |> Function.tupled((a, b) => b + a)]

为了您的最后一个例子,想不出什么比模式匹配更好

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