【问题标题】:Scala: Compare all elements in a huge listScala:比较一个巨大列表中的所有元素
【发布时间】:2023-03-22 09:03:02
【问题描述】:

请就算法和实现提出建议,以比较 Scala 中很长列表中的元素。我有一个包含数千个字符串的列表(来自 SQL),我需要将每个列表元素与该列表中的所有其他元素进行比较。

因此,我需要获取元组列表:List[(String, String, Boolean)] 其中前两个元素是要匹配的字符串,第三个是结果。

对于 N 个元素的列表,到目前为止,我的算法如下:

  1. 占据榜首
  2. 将 head 与列表中剩余的 N-1 个元素进行比较
  3. 从旧列表的尾部创建新列表,并使用这个包含 N -1 个元素的新列表完成上述所有工作:

代码:

   /**
   * Compare head of the list with each remaining element in this list
   */
  def cmpel(
    fst: String, lst: List[String],
    result: List[(String, String, Boolean)]): List[(String, String, Boolean)] = {

    lst match {
      case next :: tail => cmpel(fst, tail, (fst, next, fst == next) :: result)
      case nill => result.reverse
    }
  }

  /**
   * Compare list elements in all combinations of two
   */
  def cmpAll(lst: List[String],
    result: List[(String, String, Boolean)]): List[(String, String, Boolean)] = {
    lst match {
      case head :: tail => cmpAll(tail, result ++ cmpel(head, tail, List()))
      case nill => result
    }
  }

  def main(args: Array[String]): Unit = {
    val lst = List[String]("a", "b", "b", "a")
    println(cmpAll(lst, List()))
  }

结果:

 List((a,b,false), (a,b,false), (a,a,true), (b,b,true), (b,a,false), (b,a,false))

谢谢!

【问题讨论】:

  • 你对这一切的结果做了什么?它看起来更像是你应该在数据库中做的事情,而不是在 scala 代码中
  • 顺序重要吗?否则,您可以对它们进行排序(或从 SQL 中按排序顺序获取它们)。如有必要,请使用原始订单的另一列。只有当您有重复项时,您的比较才能相等,因此您可以在一次扫描列表中做到这一点 为它等于的其他元素的每个条目保留一个列表。必要时按原顺序重新排序。
  • 一般情况下,我需要对每两个字符串进行近似匹配。所以我认为排序无济于事
  • 好的。然后呢?你如何处理近似匹配的对?有多少会匹配?您是否需要结果列表中的所有对,或者您可以只组装匹配的(或不匹配的)并假设任何不存在的对必须具有其他结果?近似匹配标准是什么? (您对您的具体问题有一个答案,我只是想知道这是否是正确的问题:))
  • 请看我的下一个相关问题:stackoverflow.com/questions/24599139/…

标签: algorithm list scala


【解决方案1】:

您可以使用tailsflatMap 方法编写更简洁和惯用的解决方案:

list.tails.flatMap {
  case x :: rest => rest.map { y =>
    (x, y, x == y)
  }
  case _ => List()
}.toList

tails 方法返回一个迭代器,该迭代器将.tail 的重复应用程序迭代到列表中。迭代器中的第一个元素是列表本身,然后是列表的尾部,以此类推,最后返回空列表。

【讨论】:

  • 谢谢! tails 会一次性还是懒惰地为所有列表尾部分配内存?我有一个巨大的输入列表,所以这可能是个问题。
  • 在 REPL 中的快速测试或查看 API 文档表明 tails 的返回类型是 Iterator,因此表示惰性。
  • @DarqMoth tails 是懒惰的,但即使它不是列表之间的结构共享(由于不变性)也意味着内存消耗只会是 O(n),而不是 O( n^2) 如果每个元素都是一个单独的列表。
  • 请看我的下一个相关问题:stackoverflow.com/questions/24599139/…
  • 值得注意的是,输入 list. 必须是 List。如果它只输入为Seq,则第一个case => 将不匹配。为避免这种情况,您可以简单地使用 .toList: mySeq.toList.tails.flatMap
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-17
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 2021-12-29
  • 2015-04-02
  • 2012-02-19
相关资源
最近更新 更多