Простой вопрос о кортеже scala
Я новичок в scala, и то, что я изучаю, tuple
.
Я могу определить кортеж следующим образом и получить элементы:
val tuple = ("Mike", 40, "New York")
println("Name: " + tuple._1)
println("Age: " + tuple._2)
println("City: " + tuple._3)
Мой вопрос:
- Как получить длину кортежа?
- Является ли tuple изменчивым? Могу ли я изменить его элементы?
- Есть ли какая-нибудь другая полезная операция, которую мы можем сделать на кортеже?
Спасибо заранее!
Ответы
Ответ 1
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
См. scaladocs Tuple2, Tuple3 и т.д. для более.
Ответ 2
Одной вещью, которую вы также можете сделать с кортежем, является извлечение содержимого с помощью выражения 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
Ответ 3
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)
Ответ 4
Относительно вопроса 3:
Полезной вещью, которую вы можете делать с Tuples, является сохранение списков параметров для функций:
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] Как замечает Рэндалл, вам лучше использовать что-то подобное в "реальной жизни":
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 }
Обратите внимание на фигурные скобки вокруг корпуса, скобки не будут работать.
Ответ 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, кортеж - просто простой пример класса case...
Ответ 6
- Вы знаете размер кортежа, его часть этого типа. Например, если вы определяете функцию
def f(tup: (Int, Int))
, вы знаете, что длина tup
равна 2, поскольку значения типа (Int, Int)
(aka Tuple2[Int, Int]
) всегда имеют длину 2.
- Нет.
- Не совсем. Кортежи полезны для хранения фиксированного количества предметов, возможно, разных типов и передачи их, помещая их в структуры данных и т.д. Там действительно мало что можно сделать с ними, кроме создания кортежей и извлечения содержимого из кортежей.
Ответ 7
Ответы 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
Ответ 8
Используя 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
имеет тип String
, concat
имеет тип (String, Int, Boolean, Double, Double, Long)
и т.д.)
Последний метод выше (.to[Collection]
) должен быть доступен в следующей версии (по состоянию на 2014/07/19).
Вы также можете "обновить" кортеж
val a = t.updatedAt(1, 3) // gives ("a", 3, true, 0.0)
но это вернет новый кортеж вместо того, чтобы мутировать исходный.