[英]Interval merge using Spark Scala
我有我想在有重疊時合並的間隔列表。
示例: List((1,1),(2,2),(4,4),(5,5))
這里想要的輸出是List((1,2),(4,5))
我有一個價值 2.5GB 的數字列表,我想將其轉換為 Ranges 。
注意:輸入列表中沒有重復項
val l = List(List((1,1)),List((2,2)),List((4,4)),List((5,5)))
val list =sc.parallelize(l)
def merge(r1:(Int,Int),r2:(Int,Int)) :(Int,Int) = {
if(r1._2+1==r2._1) (r1._1,r2._2)
else if(r2._2+1 == r1._1) (r2._1,r1._2)
else null
}
val res = list.reduce((x,y) =>{
x.map(r1 => {
y.map(r2 => {
val m = merge(r1,r2)
m match {
case null => List(r1,r2)
case _ => List(m)
}
}).flatten
}).flatten
})
res: List[(Int, Int)] = List((4,5), (2,2), (1,2))
實際輸出是res: List[(Int, Int)] = List((4,5), (2,2), (1,2))
其中正如我所期望的List((4,5),(1,2))
。
編輯:我的解決方案
我嘗試了以下代碼。 似乎輸入很小,但我的原始數據花費的時間太長。 還有比這更好的解決方案嗎?
def overlap(x: (Int,Int),y:(Int,Int)) = {
if(x._2==y._1) (x._1,y._2)
else if(x._1==y._2) (y._1,x._2)
else null
}
def isOverlapping(x: (Int,Int),y:(Int,Int)) = {
x._1 == y._1 || x._1 == y._2 || x._2==y._1 || x._2==y._2
}
val res = list.reduce((x,y) =>{
val z = x.map(r1 => {
y.map(r2 => {
val m = merge(r1,r2)
m match {
case null => List(r1,r2)
case _ =>{
List(m)
}
}
}).flatten
}).flatten
//-------compressing the accumulated list z to merge overlapping tuples
z.foldLeft(List[(Int,Int)]()) { (acc, i) => {
if (!acc.exists(isOverlapping(i, _)))
i +: acc
else
acc.map(x => {
val m = overlap(x,i)
m match {
case null => x
case _ => m
}
})
}}
//---------
})
res: List[(Int, Int)] = List((4,5), (1,2))
我最近解決了這個問題。 我使用 List[List[Int]] 作為我的收藏。
我的方法是使用排序集合,這樣當我們實際嘗試減少重疊間隔時,我們利用排序(我們使用開始位置作為鍵開始排序,但如果兩個開始位置相等,我們使用結束位置)並且可以以 O(nlogn) 的復雜度完成問題。 我專門使用了排序集,以便如果有重復的間隔,則在我們進一步減少它們之前將其刪除。
一旦集合被排序,那么我們只需要檢查相鄰對是否重疊。 我通過檢查 1stPair.end >= 2ndPair.Start 來做到這一點。 如果為真,則表示 Pairs 重疊,我們可以通過 (1stPair.start,max(1stPair.end,2ndPair.end)) 將這 2 Pairs 更改為 1 pairs。 這里不需要檢查對之間的開始間隔,因為它是有序的,所以 2ndPair.start 將始終 >= 1stPair.start。 這是我們使用排序集合獲得的節省。
我假設,如果這些對彼此相鄰而沒有重疊,我仍然認為這是重疊並減少了它。 例如([1,2],[2,3] 減少到 [1,3])。 整個解決方案的時間復雜度就是排序的復雜度。 由於我使用SortedSet自帶的內置排序算法,我猜它提供了最快的排序(O(nlogn)。為了減少間隔,它只通過1次通過集合,所以復雜度是線性的。比較這些復雜度和“O( n)”不如“O(nlogn)”重要。所以整體復雜度是“O(nlogn)”。這是在Scala Worksheet中運行並檢查其他幾個輸入,它工作正常。
import scala.collection.SortedSet
object order extends Ordering[List[Int]] {
override def compare(a: List[Int], b: List[Int]): Int = {
if (a(0) != b(0)) a(0) - b(0)
else a(1) - b(1)
}
}
val sorted_input = SortedSet(List(6, 9), List(1, 4), List(3, 5), List(8, 12))(order)
def deduce(list: List[List[Int]], pair: List[Int]): List[List[Int]] = {
val finalList = (pair, list) match {
case (pair, head :: tail) if (pair(0) <= head(1)) => List(head(0), if (pair(1) > head(1)) pair(1) else head(1)) :: tail
case (pair, emptyList) => pair :: emptyList
}
finalList
}
sorted_input.foldLeft(List[List[Int]]())(deduce) //> res0: List[List[Int]] = List(List(6, 12), List(1, 5))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.