Подтвердить что ты не робот

Простой вопрос о кортеже scala

Я новичок в scala, и то, что я изучаю, tuple.

Я могу определить кортеж следующим образом и получить элементы:

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

Мой вопрос:

  • Как получить длину кортежа?
  • Является ли tuple изменчивым? Могу ли я изменить его элементы?
  • Есть ли какая-нибудь другая полезная операция, которую мы можем сделать на кортеже?

Спасибо заранее!

4b9b3361

Ответ 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)

но это вернет новый кортеж вместо того, чтобы мутировать исходный.