【问题标题】:Group List elements with a distance less than x将距离小于 x 的列表元素分组
【发布时间】:2014-10-01 15:41:50
【问题描述】:

我正在尝试找出一种方法来根据元素之间的 x 距离对列表中的所有对象进行分组。

例如,如果距离是1 那么

List(2,3,1,6,10,7,11,12,14)

会给

List(List(1,2,3), List(6,7), List(10,11,12), List(14))

我只能想出一些棘手的方法和循环,但我想一定有一个更干净的解决方案。

【问题讨论】:

    标签: scala scala-collections


    【解决方案1】:

    您可以尝试对列表进行排序,然后在其上使用 foldLeft。基本上是这样的

      def sort = {
        val l = List(2,3,1,6,10,7,11,12,14)
        val dist = 1
        l.sorted.foldLeft(List(List.empty[Int]))((list, n) => {
          val last = list.head
          last match {
            case h::q  if Math.abs(last.head-n) > dist=> List(n) :: list
            case _ => (n :: last ) :: list.tail 
          }
        }
        )
      }
    

    结果似乎还可以,但结果相反。如果需要,在需要时在列表中调用“reverse”。代码变成了

        val l = List(2,3,1,6,10,7,11,12,14)
        val dist = 1
        val res = l.sorted.foldLeft(List(List.empty[Int]))((list, n) => {
           val last = list.head
           last match {
             case h::q  if Math.abs(last.head-n) > dist=> List(n) :: (last.reverse :: list.tail)
            case _ => (n :: last ) :: list.tail
          }
        }
    ).reverse
    

    【讨论】:

    • 这看起来很完美,但是子列表是相反的。 h::q 语句是什么意思?
    • 如果已排序,为什么需要 Math.abs? n 总是比 last.head 大?
    • @Paul :我认为是某种反射。
    • user3729739 : h :: q 匹配列表,将其分成两部分:它的头部(h,列表的第一个元素)和它的尾部(q,通过取最后一个并删除它的第一个元素)
    • @Agemen 感谢您的回答和解释。我想为了让子列表排序,我们必须使用运算符 :+ 但这会给函数增加太多复杂性(O(n)),对吧?
    【解决方案2】:

    最干净的答案将依赖于一种可能应该称为groupedWhile 的方法,该方法将在条件为真的地方准确拆分。如果你有这个方法,那就是

    def byDist(xs: List[Int], d: Int) = groupedWhile(xs.sorted)((l,r) => r - l <= d)
    

    但我们没有groupedWhile

    让我们做一个:

    def groupedWhile[A](xs: List[A])(p: (A,A) => Boolean): List[List[A]] = {
      val yss = List.newBuilder[List[A]]
      val ys = List.newBuilder[A]
      (xs.take(1) ::: xs, xs).zipped.foreach{ (l,r) =>
        if (!p(l,r)) {
          yss += ys.result
          ys.clear
        }
        ys += r
      }
      ys.result match {
        case Nil => 
        case zs => yss += zs
      }
      yss.result.dropWhile(_.isEmpty)
    }
    

    既然你有了通用能力,你就可以很容易地获得特定的能力。

    【讨论】:

      猜你喜欢
      • 2021-07-14
      • 1970-01-01
      • 1970-01-01
      • 2017-06-25
      • 2017-06-15
      • 1970-01-01
      • 2019-06-14
      • 1970-01-01
      • 2018-02-15
      相关资源
      最近更新 更多