递归累积集合的元素

时间:2014-09-30 08:26:41

标签: scala recursion

我有一组具有整数范围的元素,例如

case class Element(id: Int, from: Int, to: Int)
val elementColl: Traversable[Element]

我希望将它们累积到

case class ElementAcc(ids: List[Int], from: Int, to: Int)

根据以下算法:

  1. 从我的Element中选择一个elementColl,然后使用它创建一个新的ElementsAcc,该ElementelementColl采用的内容相同。
  2. Element中的剩余元素进行迭代,以查找与ElementAcc具有重叠整数范围的ElementAcc
  3. 如果找到,请将其添加到ElementAcc并展开整数范围Element以包含新elementColl
  4. 的范围
  5. 如果找不到任何内容,请对ElementAcc尚未分配给ElementAcc
  6. 的其余元素重复上述过程

    这应该导致elementColl的收集。虽然只是递归地向累加器添加元素似乎很容易,但我不知道如何处理Element缩小的大小,因此我不会将相同的ElementAcc添加到多个{{1}}的

    编辑:我认为我不清楚范围的扩展。所以让我在一个例子中澄清这个:

    我的累加器当前的范围是1到5.一个范围从6到8的元素与累加器范围不重叠,因此不会包含在内。范围为4到7的元素会重叠,将包含在内,结果累加器的范围为1到7。

1 个答案:

答案 0 :(得分:3)

我会这样:

1)编写一个带ElementAccElement的函数并返回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))