开发者

Simple question about tuple of scala

开发者 https://www.devze.com 2023-01-08 20:46 出处:网络
I\'m new to scala, and what I\'m learning is tuple. I can define a tuple as following, and get the items:

I'm new to scala, and what I'm learning is tuple.

I can define a tuple as following, and get the items:

val tuple = ("Mike", 40, "New York")
println("Name: " + tuple._1)
println("Age: 开发者_运维问答" + tuple._2)
println("City: " + tuple._3)

My question is:

  1. How to get the length of a tuple?
  2. Is tuple mutable? Can I modify its items?
  3. Is there any other useful operation we can do on a tuple?

Thanks in advance!


1] tuple.productArity

2] No.

3] Some interesting operations you can perform on tuples: (a short REPL session)

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

See scaladocs of Tuple2, Tuple3 etc for more.


One thing that you can also do with a tuple is to extract the content using the match expression:

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))

Gives:

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


Tuples are immutable, but, like all cases classes, they have a copy method that can be used to create a new Tuple with a few changed elements:

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)


Concerning question 3:

A useful thing you can do with Tuples is to store parameter lists for functions:

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

[Edit] As Randall remarks, you'd better use something like this in "real life":

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)))

In order to extract the values from tuples in the middle of a "collection transformation chain" you can write:

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

Note the curly braces around the case, parentheses won't work.


Another nice trick ad question 3) (as 1 and 2 are already answered by others)

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

Edit: in fact it's rather a feature of pattern matching and case classes, a tuple is just a simple example of a case class...


  1. You know the size of a tuple, it's part of it's type. For example if you define a function def f(tup: (Int, Int)), you know the length of tup is 2 because values of type (Int, Int) (aka Tuple2[Int, Int]) always have a length of 2.
  2. No.
  3. Not really. Tuples are useful for storing a fixed amount of items of possibly different types and passing them around, putting them into data structures etc. There's really not much you can do with them, other than creating tuples, and getting stuff out of tuples.


1 and 2 have already been answered.

A very useful thing that you can use tuples for is to return more than one value from a method or function. Simple example:

// 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


Using shapeless, you easily get a lot of useful methods, that are usually available only on collections:

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]

Everything is typed as one would expect (that is first has type String, concat has type (String, Int, Boolean, Double, Double, Long), etc.)

The last method above (.to[Collection]) should be available in the next release (as of 2014/07/19).

You can also "update" a tuple

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

but that will return a new tuple instead of mutating the original one.

0

精彩评论

暂无评论...
验证码 换一张
取 消