2016-05-11 4 views
2

я бы подумал, что список кортежей может быть легко сплющенные:Сгладить список кортежей в Scala?

scala> val p = "abcde".toList 
p: List[Char] = List(a, b, c, d, e) 

scala> val q = "pqrst".toList 
q: List[Char] = List(p, q, r, s, t) 

scala> val pq = p zip q 
pq: List[(Char, Char)] = List((a,p), (b,q), (c,r), (d,s), (e,t)) 

scala> pq.flatten 

Но вместо этого, это происходит:

<console>:15: error: No implicit view available from (Char, Char) => scala.collection.GenTraversableOnce[B]. 
     pq.flatten 
     ^

я могу получить работу с:

scala> (for (x <- pq) yield List(x._1, x._2)).flatten 
res1: List[Char] = List(a, p, b, q, c, r, d, s, e, t) 

Но я не понимаю сообщение об ошибке. И мое альтернативное решение кажется запутанным и неэффективным.

Что означает это сообщение об ошибке и почему я не могу просто сгладить список кортежей?

ответ

10

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

pq.flatten {case (a,b) => List(a,b)} 

Если это делается несколько раз по всему коду, вы можете сохранить некоторый шаблон, сделав его неявным. Ответ

scala> import scala.language.implicitConversions 
import scala.language.implicitConversions 

scala> implicit def flatTup[T](t:(T,T)): List[T]= t match {case (a,b)=>List(a,b)} 
flatTup: [T](t: (T, T))List[T] 

scala> pq.flatten 
res179: List[Char] = List(a, p, b, q, c, r, d, s, e, t) 
+1

Пожалуйста, не используйте неявные преобразования, когда оба источника и тип цели являются общими. Смешайте это, например. auto-tupling, и вы получаете всевозможные дурацкие вещи. Получил метод, который принимает список строк? Внезапно 'foo (" a "," b ")' работает, но 'foo (" a "," b "," c ")' не делает. И дальше и дальше ... –

+1

Точка. Имплициты по своей природе слишком «призрачны» и, вероятно, их следует избегать в случайных ситуациях, подобных этому. – jwvh

2

jwvh охватывает «кодирование» решение вашей проблемы отлично, поэтому я не буду вдаваться в подробности о том, что. Единственное, что я хотел добавить, было уточнение , почему решение, которое вам и вам нужно найти jwvh.

Как указано в библиотеке Scala, Tuple2 (который переводит к (,)) является:

Кортеж из 2-х элементов; каноническое представление Product2.

И следуя на что:

Product2 является декартовым произведением 2-х компонентов.

... который means, что Tuple2[T1,T2] представляет:

Множество всех возможных пар элементов, компоненты которых являются членами двух множеств (все элементы в T1 и T2 соответственно).

List[T], с другой стороны, представляет собой упорядоченные коллекции T элементов.

Что все это означает практически, что нет абсолютного пути, чтобы перевести любые возможные Tuple2[T1,T2] к List[T], просто потому, что T1 и T2 могут быть разными.Например, возьмите следующий кортеж:

val tuple = ("hi", 5) 

Как можно сгладить такой кортеж? Должно ли 5 сделать String? Или, может быть, просто сгладить до List[Any]? Хотя оба эти решения могут быть использованы, они работают вокруг системы типов, поэтому они не кодируются в API Tuple по дизайну.

Все это сводится к тому, что для этого случая нет неявного представления по умолчанию, и вы должны сами поставить его, как и jwvh, и вы уже поняли.

+0

Таким образом, в основном преобразование, предоставляемое @jwvh, гарантирует, что члены кортежей имеют одинаковый тип (T, T). Это позволит им сгладить (a, b) => Список (a, b). Хорошее объяснение (: –

+1

@mdm: преобразование из 'Tuple2 [T1, T2]' в 'List [T]' действительно не очевидно, но 'Tuple2 [T, T]' -> 'List [T]' включен с другой стороны, довольно просто. Я не думаю, что есть веская причина, по которой scala не предоставляет его. Если я могу сгладить «List [Option [T]]», я должен был бы сделать то же самое с «List [ T, T)], 'List [(T, T, T)]" и т. Д. – Dima

+1

@Dima, почему, когда отлично существует 'Seq' (и др.)? Я думаю, что прецеденты ограничены (и , в некоторых случаях это было бы совершенно неправильно). Для типичного использования '(x, y)' для хранения координат. 'x' и' y' все еще не одно и то же, и 'flatten' будет очень неуместным Операции. Кортежи - это больше, чем последовательность, возможно, разных типов. Индекс внутри них также очень важен и неявно предоставляет операции, которые несколько игнорируют, что не является хорошей идеей (конечно, все очень «в основном мнения», но это нормально в комментарии). –