2010-07-27 109 views
22

我是scala的新手,我正在學習的是tuple關於scala元組的簡單問題

我可以定義一個元組如下,並獲得項目:

val tuple = ("Mike", 40, "New York") 
println("Name: " + tuple._1) 
println("Age: " + tuple._2) 
println("City: " + tuple._3) 

我的問題是:

  1. 如何獲得一個元組的長度是多少?
  2. 元組是否可變?我可以修改它的項目嗎?
  3. 是否有任何其他有用的操作,我們可以做一個元組?

在此先感謝!

回答

39

1] tuple.productArity

2號

3]你可以在元組進行一些有趣的操作:(短REPL會話)

scala> val x = (3, "hello") 
x: (Int, java.lang.String) = (3,hello) 

scala> x.swap 
res0: (java.lang.String, Int) = (hello,3) 

scala> x.toString 
res1: java.lang.String = (3,hello) 

scala> val y = (3, "hello") 
y: (Int, java.lang.String) = (3,hello) 

scala> x == y 
res2: Boolean = true 

scala> x.productPrefix 
res3: java.lang.String = Tuple2 

scala> val xi = x.productIterator 
xi: Iterator[Any] = non-empty iterator 

scala> while(xi.hasNext) println(xi.next) 
3 
hello 

Tuple2 scaladocs, Tuple3等等。

+0

λG,再次感謝您! – Freewind 2010-07-27 13:32:12

+0

@Freewind,歡迎光臨! – missingfaktor 2010-07-27 13:34:11

4
  1. 你知道一個元組的大小,它是它的一部分。例如,如果你定義一個函數def f(tup: (Int, Int)),你知道的tup長度爲2,因爲(Int, Int)型(又名Tuple2[Int, Int])的值總是有2
  2. 不是一個真正的長度。元組對於存儲固定數量的可能不同類型的項目以及將它們傳遞給數據結構等很有用。除了創建元組以及從元組中取出元素之外,實際上用戶可以做的事情不多。
11

Tuples是不可改變的,但是,像所有的情況下類,它們可用於創建一個新的Tuple有一些改變元素複製方法:

scala> (1, false, "two") 
res0: (Int, Boolean, java.lang.String) = (1,false,two) 

scala> res0.copy(_2 = true) 
res1: (Int, Boolean, java.lang.String) = (1,true,two) 

scala> res1.copy(_1 = 1f) 
res2: (Float, Boolean, java.lang.String) = (1.0,true,two) 
17

一件事,你也可以做一個元組是使用match表達式來提取內容:

def tupleview(tup: Any){ 
    tup match { 
    case (a: String, b: String) => 
     println("A pair of strings: "+a + " "+ b) 
    case (a: Int, b: Int, c: Int) => 
     println("A triplet of ints: "+a + " "+ b + " " +c) 
    case _ => println("Unknown") 
    } 
} 

tupleview(("Hello", "Freewind")) 
tupleview((1,2,3)) 

給出:

A pair of strings: Hello Freewind 
A triplet of ints: 1 2 3 
+0

感謝這個很好的例子 – Freewind 2010-07-27 13:43:55

5

另一個不錯的伎倆廣告的問題3)(如圖1和2都已經被別人回答)

val tuple = ("Mike", 40, "New York") 
tuple match { 
    case (name, age, city) =>{ 
    println("Name: " + name) 
    println("Age: " + age) 
    println("City: " + city) 
    } 
} 

編輯:其實這是相當模式匹配和case類的功能,一個元組僅僅是一個簡單的例子的案例分類...

+0

謝謝,有幫助 – Freewind 2010-07-27 13:44:16

4

1和2已經被回答。

可以使用元組的一個非常有用的事情是從方法或函數返回多個值。簡單的例子:

// Get the min and max of two integers 
def minmax(a: Int, b: Int): (Int, Int) = if (a < b) (a, b) else (b, a) 

// Call it and assign the result to two variables like this: 
val (x, y) = minmax(10, 3)  // x = 3, y = 10 
7

關於問題3:

你可以用元組做一個有用的東西是存儲參數列表的功能:

def f(i:Int, s:String, c:Char) = s * i + c 
List((3, "cha", '!'), (2, "bora", '.')).foreach(t => println((f _).tupled(t))) 
//--> chachacha! 
//--> borabora. 

[編輯]作爲蘭德爾話,你」 d更好地在「現實生活」中使用類似這樣的東西:

def f(i:Int, s:String, c:Char) = s * i + c 
val g = (f _).tupled 
List((3, "cha", '!'), (2, "bora", '.')).foreach(t => println(g(t))) 

爲了提取值從在「集合轉型鏈」中間元組,你可以寫:

val words = List((3, "cha"),(2, "bora")).map{ case(i,s) => s * i } 

注意周圍的情況下,大括號,括號中是行不通的。

+3

請注意,在這個構造中,你將綜合函數的元組版本,這個函數本身在'foreach' *的每次迭代中都從方法'f' *中解除。 – 2010-07-27 23:35:55

1

使用shapeless,您可以輕鬆地得到了很多有用的方法,即通常僅適用於類別:

import shapeless.syntax.std.tuple._ 

val t = ("a", 2, true, 0.0) 

val first = t(0) 
val second = t(1) 
// etc 

val head = t.head 
val tail = t.tail 
val init = t.init 
val last = t.last 

val v = (2.0, 3L) 

val concat = t ++ v 
val append = t :+ 2L 
val prepend = 1.0 +: t 

val take2 = t take 2 
val drop3 = t drop 3 

val reverse = t.reverse 

val zip = t zip (2.0, 2, "a", false) 
val (unzip, other) = zip.unzip 

val list = t.toList 
val array = t.toArray 
val set = t.to[Set] 

一切都被分類爲人們所期望的(即first具有類型Stringconcat具有類型(String, Int, Boolean, Double, Double, Long)等)

上一個最後的方法(.to[Collection])應該在下一個版本中(截至2014/07/19)提供。

您也可以「更新」的元組

val a = t.updatedAt(1, 3) // gives ("a", 3, true, 0.0) 

,但將返回,而不是突變,原來的一個新的記錄。