2011-08-20 47 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