我有一组具有整数范围的元素,例如
case class Element(id: Int, from: Int, to: Int)
val elementColl: Traversable[Element]
我希望将它们累积到
中case class ElementAcc(ids: List[Int], from: Int, to: Int)
根据以下算法:
Element
中选择一个elementColl
,然后使用它创建一个新的ElementsAcc
,该Element
与elementColl
采用的内容相同。Element
中的剩余元素进行迭代,以查找与ElementAcc
具有重叠整数范围的ElementAcc
。ElementAcc
并展开整数范围Element
以包含新elementColl
ElementAcc
尚未分配给ElementAcc
这应该导致elementColl
的收集。虽然只是递归地向累加器添加元素似乎很容易,但我不知道如何处理Element
缩小的大小,因此我不会将相同的ElementAcc
添加到多个{{1}}的
编辑:我认为我不清楚范围的扩展。所以让我在一个例子中澄清这个:
我的累加器当前的范围是1到5.一个范围从6到8的元素与累加器范围不重叠,因此不会包含在内。范围为4到7的元素会重叠,将包含在内,结果累加器的范围为1到7。
答案 0 :(得分:3)
我会这样:
1)编写一个带ElementAcc
和Element
的函数并返回ElementAcc
。
该函数看起来像:
def extend(acc: ElementAcc, e: Element): ElementAcc = {
if(acc.from <= e.from && e.from <= acc.to)
ElementAcc(e.id :: acc.ids, acc.from, math.max(acc.to, e.to))
else if (acc.from <= e.to && e.to <= acc.to)
ElementAcc(e.id :: acc.ids, math.min(acc.from, e.from), acc.to)
else acc
}
累积对象时, foldLeft
通常是很好的解决方案。
它需要一个累加器的初始值和一个带累加器和元素并返回累加器的函数。然后它累积traversable
的所有元素。
编辑:
2)要累积在不同的列表上,您必须创建另一个函数来合并List[ElementAcc]
和Element
:
def overlap(acc: ElementAcc, e: Element): Boolean = {
(acc.from <= e.from && e.from <= acc.to) || (acc.from <= e.to && e.to <= acc.to)
}
def dispatch(accList: List[ElementAcc], e: Element): List[ElementAcc] = accList match {
case Nil => List(ElementAcc(List(e.id), e.from, e.to))
case acc :: tail =>
if (overlap(acc, e)) extend(acc, e) :: tail
else acc :: dispatch(tail, e)
}
3)它与foldLeft一起使用:
val a = Element(0, 0, 5)
val b = Element(1, 3, 8)
val c = Element(2, 20, 30)
val sorted = List(a, b, c).foldLeft(List[ElementAcc]())(dispatch)
sorted: List[ElementAcc] = List(ElementAcc(List(1, 0),0,8), ElementAcc(List(2),20,30))