Scala:在字符串列表中查找最常用的X字符串

时间:2017-02-25 13:28:30

标签: scala

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

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

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

示例:我有此列表(“Hello”,“Heyo”,“Hel”),输出应为“He”表示k = 2,“Hel”表示k = 3 < / p>

2 个答案:

答案 0 :(得分:3)

非常传统的答案:)

  • 使用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

答案 1 :(得分: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的答案显示了如何做到这一点)