Манипулирующие кортежи - PullRequest
7 голосов
/ 20 августа 2011

Есть ли способ манипулировать несколькими значениями кортежа без использования временной переменной и запуска нового оператора?

Скажем, у меня есть метод, который возвращает кортеж, и я хочу сделать что-то с этими значениями в строке.

например. если я хочу разбить строку в определенной точке и перевернуть куски

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

(работает, но выглядит немного грязно, создавая для этого только один элемент List) или

s.splitAt(n).swap.productIterator.mkString

(работает для этого конкретного примера, но только потому, что есть метод swap, который делает то, что я хочу, поэтому он не очень общий).

Метод zipped для кортежей, похоже, предназначен только для кортежей списков.

В качестве другого примера, как вы могли бы превратить кортеж ('a, 'b, 'c) в ('b, 'a, 'c) в одном выражении?

Ответы [ 4 ]

9 голосов
/ 20 августа 2011

Кортежи являются просто удобным типом возврата, и не предполагается, что вы будете делать сложные манипуляции с ним.Также было подобное обсуждение на форумах Scala.

В последнем примере не удалось найти ничего лучше сопоставления с образцом.

('a, 'b, 'c) match { case (a, b, c) => (b, a ,c) }
7 голосов
/ 20 августа 2011

К сожалению, встроенные методы для кортежей довольно ограничены .

Может быть, вы хотите что-то подобное в своей личной библиотеке,

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)

Альтернативой последнему выражению будет оператор "pipe" |> (получить его из Scalaz или здесь ),

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 голосов
/ 20 августа 2011

Как насчет этого?

s.splitAt(n) |> Function.tupled(_ + _)

[Редактировать: только что заметил, ваши аргументы для функции обращены.В этом случае вам придется отказаться от синтаксиса заполнителя и вместо этого перейти к: s.splitAt(n) |> Function.tupled((a, b) => b + a)]

В последнем примере не может придумать ничего лучше, чем сопоставление с образцом (как показано @ 4e6.)

0 голосов
/ 20 июля 2014

С текущей версией разработки бесформенный , вы можете достичь этого, не распаковывая кортеж:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...