2017-12-06 8 views
2

2つのリストから共通の要素をフィルタリングし、残りの2つのリストを残したい。2つのシーケンスから共通のエントリをフィルタリングし、元のユニークなエントリを持つ2つのリストを返す

私はスカラ座での2つの配列を有する:

val firstSeq = Seq(1,2,3,4) 
val secondSeq = Seq(1,3,5,7) 

をそして私がやりたいことは、私はで終わる意味している共通の要素の全て、フィルタです:

ので
filteredFirstSeq = Seq(2,4) 
filteredSecondSeq = Seq(5,7) 

、ありますスカラーでここに行く簡単な方法:

val filteredFirstSeq = firstSeq.filterNot(firstEntry => secondSeq.contains(firstEntry)) 
val filteredSecondSeq = secondSeq.filterNot(secondEntry => firstSeq.contains(secondEntry)) 

しかし!これは、最初のリスト全体を実行しなければならないことを意味し、の2番目のリスト全体が一致し、リストが大きく、エントリが整数よりも複雑です。

私は一度すべてを繰り返すだけでよいと思いますが、そうすることができると思う唯一の方法は、変更可能なリストを作成し、一致するものが見つかるたびに値を取り除くことです。しかし、少し厄介なようです。私は、私が行方不明になっていることに対する些細な答えがなければならないと確信しています。

ありがとうございました!

+1

を保証していますか?たとえば、個々のリストに重複がありますか? – Tyler

+1

'firstSeq diff secondSeq'とその補数' secondSeq diff firstSeq'は、あなたが望むものを得るためのもっと簡潔なメソッドです。残念ながら、明らかに単一のトラバーサルではありません。 – jwvh

答えて

2

この例では、各リストに重複が含まれていないことを前提としています。そうでない場合、折りたたみ内のロジックはわずかに変更する必要があります。

val firstSeq = Seq(1,2,3,4) 
val secondSeq = Seq(1,3,5,7) 

// Put everything into a list, keeping track of where things came from 
val both: Seq[(Int, Int)] = firstSeq.map(x => (x, 1)) ++ secondSeq.map(x => (x, 2)) 

// Reduce the list into a single map, where the keys are the numbers, and the value is the originating seq. Anytime we try to insert a value that already is in the map, we remove the value instead, since that will mean the value was in each sequence. 
val map: Map[Int, Int] = both.foldLeft(Map.empty[Int, Int]) { (map, tuple) => 
    val (value, seqNumber) = tuple 
    if (map.contains(value)) { 
    map - value 
    } else { 
    map + (value -> seqNumber) 
    } 
} 

// Now partition the values back into their original lists 
val (firstSeqFiltered, secondSeqFiltered) = map.partition(_._2 == 1) 
println(firstSeqFiltered.keys) 
println(secondSeqFiltered.keys) 

出力:リストは私のユニークに

Set(2, 4) 
Set(5, 7) 
関連する問題