Дан:Scala - Свести Seq, содержащий Seq
Seq(1,2,3) map {
case 1 => 11
case 2 => Seq(12,13,14)
case 3 => 15
}
Как элегантно придавить это к Seq[Int]
, содержащей Seq(11,12,13,14,15)
?
Дан:Scala - Свести Seq, содержащий Seq
Seq(1,2,3) map {
case 1 => 11
case 2 => Seq(12,13,14)
case 3 => 15
}
Как элегантно придавить это к Seq[Int]
, содержащей Seq(11,12,13,14,15)
?
Вот один из способов сделать это:
Seq(1,2,3) flatMap {
case 1 => Seq(11)
case 2 => Seq(12,13,14)
case 3 => Seq(15)
}
res0: Seq [Int] = List (11, 12, 13, 14, 15)
Если у вас уже есть этот список, вы можете сделать flatMap
для достижения требуемого результата:
val list = Seq(11, Seq(12, 13, 14), 15)
val flattened = list.flatMap {
case x: Int => Seq(x)
case y: Seq[Int] => y
}
чтобы избежать предупреждений (хотя, это не поможет вам сделать этот код типобезопасный), вы можете использовать следующее:
val flattened = list.flatMap {
case x: Int => Seq(x)
case y: Seq[_] => y.asInstanceOf[Seq[Int]]
}
Вы попробовали? Вы получите предупреждение о стирании стилей и получите Seq [Any], а не Seq [Int]. 'case y: Seq [_] => y' немного упростит, что информация о том, что находится в последовательности, потеряна (и избегает предупреждения). –
@Paul Mmm, я получаю это предупреждение, тем не менее, тип 'flattened' -' Seq [Int] '. –
Я не понимаю, как это может быть. Попробуйте 'val list = Seq (11, Seq (" s "," y "," x "), 15)', но не изменяйте свое определение 'flattened'. Он работает без ошибок, но определенно не возвращает 'Seq [Int]'! –
Вот еще один способ сделать это:
implicit def unitSeq[T](x: T): Seq[T] = Seq(x)
Seq(1, 2, 3) flatMap {
case 1 => 11
case 2 => Seq(12, 13, 14)
case 3 => 15
}
res0: Seq [Int] = List (11, 12, 13, 14, 15)
Если у вас есть Seq(1,2,3)
у вас есть Seq[Int]
,
после операции карты у вас есть проблемы, хотя
val mapped = Seq(1,2,3) map {
case 1 => 11
case 2 => Seq(12,13,14)
case 3 => 15
}
Что такое тип mapped
? Разумным ответом на это может быть то, что у него нет типа. Это близко к истине. Получаемый тип: Seq[Any]
. К сожалению, это совершенно бесполезный тип. Это не то, что вы могли бы сделать что-нибудь полезное с помощью метода типа, и можно было бы сделать хороший вывод о том, что Scala не должна допускать, чтобы этот тип был выведен в первую очередь.
Решение состоит в том, чтобы не допустить, чтобы это было далеко в первую очередь, но сопоставимо с тем, что имеет разумный тип. Решение показано Саймоном разумный подход:
val mapped = Seq(1,2,3) map {
case 1 => Seq(11)
case 2 => Seq(12,13,14)
case 3 => Seq(15)
case _ => throw new Exception("uh oh, didn't account for this to happen!")
}
Теперь отображается это Seq[Seq[Int]]
, и мы можем сделать более полезные вещи с ним, например, придавить его к Seq[Int]
с mapped.flatten
Но мы можем получить там в один ход. Существует операция под названием flatMap
по адресу Seq[A]
, которая принимает функцию A => Seq[A]
как аргумент и возвращает один Seq[A]
.
val flatmapped = Seq(1,2,3) flatMap {
case 1 => Seq(11)
case 2 => Seq(12,13,14)
case 3 => Seq(15)
case _ => throw new Exception("uh oh, didn't account for this to happen!")
}
flatmapped
теперь Seq(11, 12, 13, 14, 15)
Помимо
Оказывается, кстати, что это очень полезно иметь эту операцию на всех видах параметризованных типов: (F[A], A => F[A]) => F[A]
Например:
Option[A].flatMap(a: A => Option[A]): Option[A]
def squareroot(x: Double): Option[Double] = if (x >= 0) Some(Math.sqrt(x))
else None
Some(4.0).flatMap(squareroot) == Some(2.0)
Some(-1.0).flatMap(squareroot) == None
None.flatMap(squareroot) == None
или
Future[A].flatMap(a: A => Future[A]): Future[A]
Эта операция иногда называют flatMap
, а иногда называют bind
, а иногда представлен в виде =>>
, и если тип (назовем его F[A]
), которые поддерживают эту операцию, и поддерживают еще одну операцию который может создать F[A]
от A
(иногда называется point
, а иногда и называется return
) и следуйте некоторым условиям, как эти операции составляют, F[A]
формирует Monad
'Скала не должна была допускать, чтобы этот тип был выведен в первую очередь. 'Вы получаете предупреждение об этом, хотя –
По умолчанию? Я этого не знал, но это прогресс :) – Martijn
Вы действительно решили проблему OP? Мне кажется, этот список уже создан, и вы должны сгладить его, не так ли? –
@DmitryGinzburg Я предполагаю, что OP понадобится сделать адаптацию для решения реальной проблемы, но мы не можем точно знать, что это такое. Это показывает, что вы можете сопоставить входы с 'Seq' и использовать 'flatMap' для решения этой проблемы. – Simon