【发布时间】:2019-10-14 21:32:04
【问题描述】:
我有一个区间列表,只要有重叠,我想合并它们。
示例:List((1,1),(2,2),(4,4),(5,5))
这里想要的输出是List((1,2),(4,5))
我有一个价值 2.5GB 的数字列表,我想将其转换为范围。
注意:输入列表中没有重复项
步骤
- 输入:List[Int] .
- 映射到元组列表:List((a,a),(b,b), ...)。
- 使用范围合并逻辑减少它。
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((1,1),(2,2),(4,4),(5,5))似乎具有相同的值,每个元组都是这种情况吗?在您的示例中,元组也是排序的。总是这样吗? -
@AlexandrosBiratsis 是的,元组中存在相同的值,它们也已排序。
-
@C.S.ReddyGadipally 在你看到连续的元组时合并,即如果有
List((1,1),(2,2)),它应该合并为List((1,2)) -
@Learner,输入 List((1,1),(2,2),(3,3),(4,4),(5,5)) 的输出应该是什么?
标签: scala apache-spark reduce