2016-08-24 1 views
0

Seq [Seq [Int]をどのように変形して、各内部Seqに他の2つのリストの要素が含まれるようにすることができますか?Scala - 複数のSeqを折りたたみます

//Example: 
val A = Seq(1, 2, 3) 
val B = Seq(4, 5) 
val C = Seq(6, 7, 8) 
val input(A,B,C) 
/** 
    * INPUT: [(1,2,3), (4,5), (6,7,8)] 
    * OUTPUT:[(1,4,6), (1,4,7), (1,4,8), (1,5,6), ..., (3,5,8)] 
    */ 
def process(input: Seq[Seq[Int]]): Seq[Seq[Int]] = { 
    //unknown 
} 
+2

ソリューションの一部を私たちと出発点として共有してみませんか? – pedrofurla

+0

この回答を見る[ここ](http://stackoverflow.com/a/8218167/4496364)。 –

+0

あなたがより多くの 'Seq'オブジェクトで終わると、何かが崩壊しているようには見えません。 – Eric

答えて

1

これは宿題であれば、私はあなたが(あなたは私が推測するそれから再帰を含む簡単なソリューションをリバースエンジニアリングするかもしれません)以下で回していないお勧めします。しかし、もしあなたが本当に興味があるのであれば、かなり素敵なトリックがあります。

def convert[T](xs: Seq[Seq[T]]): Seq[Seq[T]] = 
    xs.foldLeft(Seq(Seq[T]()))((bs,ns) => for (b <- bs; n <- ns) yield b :+ n) 

foldLeft一度にあなたの方法右の1 Seq作業、入力の左側から開始されるという事実を強調しています。それで、Seqごとに、あなたは一種のデカルト積をとっています。

scala> convert(Seq(Seq(1,2,3), Seq(4,5), Seq(6,7,8))) 
res: Seq[Seq[Int]] = List(List(1, 4, 6), List(1, 4, 7), List(1, 4, 8), 
List(1, 5, 6), List(1, 5, 7), List(1, 5, 8), List(2, 4, 6), List(2, 4, 7), 
List(2, 4, 8), List(2, 5, 6), List(2, 5, 7), List(2, 5, 8), List(3, 4, 6), 
List(3, 4, 7), List(3, 4, 8), List(3, 5, 6), List(3, 5, 7), List(3, 5, 8)) 
+0

ありがとう、これは私が必要なものです。私はこれを分解して、それが何をしているのかを理解するでしょう。 –

+0

の理解には正確に何がb:+ nしていますか? –

+0

'b:+ n 'は要素' b'をSeq 'n'の前に付加します。 – Alec

0

これは、リスト(またはケースのシーケンス)のリストを操作する標準的な再帰的な概念です。キーはあなたの思考を逆転させ、それぞれの候補症例をどのように構築するかを検討することです。他のソリューションが示しているように、これを解決するにはいくつかの方法があり、そのすべてがお互いに多かれ少なかれ縮まることに注意してください。

私がここに示す解決策は、発注を除いて(意図的に)正しいです。これは、しかし、必要な概念を示すべきである:

def process(input: Seq[Seq[Int]]): Seq[Seq[Int]] = input match { 
    case Nil => Seq() 
    case head :: Nil => head.map((element: Int) => Seq(element)) 
    case (head: Seq[Int]) :: tail => process(tail).flatMap(
    (tailSeq: Seq[Int]) => { 
     head.map((element: Int) => element +: tailSeq) 
    }) 

} 

// In the worksheet 
val processResult = process(input) // Visual inspection shows correctness 
processResult.length == (A.length * B.length * C.length) // Just verify we get the correct number of values 

再帰を考えると、あなたが最初にすべきことは、あなたのベースケースを考えています。この場合、inputのリストが空の場合はどうなりますか?これは空のSeqであることがわかります。これは、その上にソリューションを構築できるので便利です。さて、私はちょっと騙して、2番目の基底のケース(反復しないケースは基底ケースです)を提案します。これは、シーケンスが1つしかないことを示しています。単一の要素。

mapを使用して、入力シーケンス(head)の各要素を単一要素シーケンスに変換または 'マップ'します。これらのすべてが一緒になって、残りのソリューションを構築する基本シーケンスです。

はその基盤を考えると、我々は inputtail)といくつかの新しいシーケンス( head)における付加的な配列の未知の数がある場合にどうなるかを考える - これは 一般的なケースと呼ばれています。 processは残りのシーケンスすべてに対して正しい解を返すと信じることができるので、 process(tail)でそれを行います。今はそれを取って headを使って変換するだけです。

また、得られた配列全体に亘ってmapが欲しい。 tailを処理してSeq(Seq(3), Seq(4))を返し、headSeq(1,2)とすると、結果としてSeq(Seq(1,3), Seq(1,4), Seq(2,3), Seq(2,4)が必要であることがわかりました。外側のマップ(実際にはflatMap)は、得られた各シーケンスを順番にとり、シーケンスの各要素mapprepend (+:)を使用します。

flatMapの代わりにmapを使用すると、結果はSeq(Seq(Seq(1,3), Seq(1,4)), Seq(Seq(2,3), Seq(2,4)))になります。flatMapが行うのは、headのマッピングを単純に「平坦化」することで、各ヘッド要素の適用結果がすべて同じシーケンスになるためです。 (読者のための運動:第二mapflatMapに置き換えている場合はどうなるか?)だから、

、我々は任意のシーケンスを追加し、正しい出力を得ることができます知っているtailの正しい処理を与えられました。これはすべて必要とされ、再帰の魔法です!

関連する問題