【问题标题】:Scala: Find the most frequent X string in a list of stringsScala:在字符串列表中查找最频繁的 X 字符串
【发布时间】:2017-02-25 13:28:29
【问题描述】:

我要做的是通过字符串列表找到给定长度的最频繁子字符串。到目前为止,我只提出了函数的签名:

def getFreqSub(lst: List[String], k: Int)

为了简单起见,我说 k 总是小于列表中每个字符串的最大字符大小,所以我不必做那个检查。我找到了一些关于此的文档,但无济于事。我想过使用 substring 函数,但是为了检查每个字母组合,比如说 k=2,它将如何工作?任何帮助/提示/链接表示赞赏。

示例:我有这个列表 ("Hello","Heyo","Hel"),对于 k = 2,输出应该是 "He",对于 k = 3,输出应该是 "Hel"

【问题讨论】:

  • lst.filter(_.length==k).??? 然后stackoverflow.com/questions/11448685/…
  • @Paul 当我尝试使用(身份)事物时出现此错误:找到:Int => Int required:String =>? d.groupBy(身份)

标签: scala


【解决方案1】:

非常传统的答案:)

  • 使用HashMap 来索引给定长度 k 的每个子字符串及其出现
  • 排序得到最频繁的子串:)

//算法

  def getFreqSub(list: List[String], k: Int): (String, Int) = {
    val index = scala.collection.mutable.Map.empty[String, Int]

    list.foreach { input =>
      for (substring <- input.sliding(k)) { // alternative to .substring(i, i + windowSize)
           index(substring) = index.getOrElse(substring, 0) + 1
      }
    }

   index.toMap.toSeq.sortBy(_._1).head
  }

//测试

val twoLetters = getFreqSub(List("Hello", "Heyo", "Hel"), 2)
assert(twoLetters._1 == "He")
assert(twoLetters._2 == 3) //occurance

val threeLetters= getFreqSub(List("Hello", "Heyo", "Hel"), 3)
assert(threeLetters._1 == "Hel")
assert(threeLetters._2 == 2) //occurance

关于IterableLike#sliding的注意事项

返回给定滑动窗口的迭代器。

val string = "HELLO"
val window = 2
string.sliding(window).foreach { substring =>
  println(substring)
}

输出

HE
EL
LL
LO

【讨论】:

  • 这比我的回答更有效率;不错
  • 不错的一个!此外,您可以将生成器替换为 sliding: for (substring
  • @AndreiT。你是对的,滑动更性感 :) 感谢您指出这一点。
【解决方案2】:

这不是很有效,但它很有效并且很容易遵循:

object q42456681 {
  def main(args: Array[String]) = {

    assert(getFreqSub(List("Hello","Heyo","Hel"), 2) == "He")
    assert(getFreqSub(List("Hello","Heyo","Hel"), 3) == "Hel")
  }

  def getFreqSub(lst: List[String], k: Int): String = {
    val allSubstrsOfDesiredLen =
      lst.flatMap { str =>
        (0 to (str.length - k)).map { startIdx =>
          str.substring(startIdx, startIdx + k)
        }
      }

    allSubstrsOfDesiredLen
      .groupBy(identity)
      .mapValues(_.length)
      .maxBy(_._2)
      ._1
  }
}

如果要搜索的字符串列表很长,则需要花时间对其进行优化。使用命令式方法并构造子字符串的哈希或树图以随着搜索的进行而计数会更有效。 (@prayagupd 的回答显示了如何做到这一点)

【讨论】:

  • 让我试一试,感谢您提前明确回复!
  • 我得到这个错误:错误:类型不匹配;发现:Int => Int 必需:String =>? .groupBy(identity) 我在 Eclipse SCALA IDE、Scala 解释器(控制台)上运行它我应该在其他地方运行它吗?对不起,愚蠢的问题,我是新人。
  • 尝试用(s)=&gt;s替换identity
  • 是的,它现在可以工作了。公认。你能给我一些关于在哪里寻找一些好的 scala 教程的提示吗?到目前为止我没有运气。
  • Odersky 等人的“Scala 编程”一书。是我所知道的最好的 Scala 学习资源。总帐
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-23
  • 2012-05-16
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
相关资源
最近更新 更多