如何在Scala中找到两个字符串的最长公共前缀?
我可能可以编写一个“命令式”解决方案(索引i
在字符串s(i) == t(i)
上运行),但我正在寻找一种“功能式”解决方案(不更新索引变量)明确地,例如)。
答案 0 :(得分:26)
scala> "helloworld".zip("hellohell").takeWhile(Function.tupled(_ == _)).map(_._1).mkString
res130: String = hello
答案 1 :(得分:4)
另一个递归版本。
def pref(s: String, t: String, out: String = ""): String = {
if (s == "" || t == "" || s(0) != t(0)) out
else pref(s.substring(1), t.substring(1), out + s(0))
}
它比sjj快10倍以上,比missfaktor快两倍。 Java的substring
很快,因为String
是不可变的。
答案 2 :(得分:3)
递归版:
def findCommonPrefix(s1 : String, s2 : String) : String = {
def findCommonPrefixR(l1: List[Char], l2 : List[Char]) : List[Char] = {
l1 match {
case Nil => Nil
case x::xs => if (l2 != Nil && l2.head == x) x :: findCommonPrefixR(xs, l2.tail) else Nil
}
}
findCommonPrefixR(s1.toList, s2.toList).mkString
}
答案 3 :(得分:2)
命令式版本可以简化为
def longestCommonPrefix(s1:String, s2:String):String = {
val maxSize = scala.math.min(s1.length, s2.length)
var i:Int = 0;
while ( i < maxSize && s1(i)== s2(i)) i += 1;
s1.take(i);
}
答案 4 :(得分:1)
如果速度是合约,那么就必须采取行动。
scala> def longestCommonPrefix(a: String, b: String): String = {
| var same = true
| val sb = new StringBuilder
| var i = 0
| while(same && i < math.min(a.length, b.length)) {
| if(a.charAt(i) != b.charAt(i)) {
| same = false
| } else {
| sb += a.charAt(i)
| i += 1
| }
| }
| sb.result
| }
longestCommonPrefix: (a: String, b: String)String
scala> longestCommonPrefix("", "")
res50: String = ""
scala> longestCommonPrefix("helloworld", "hellohell")
res51: String = hello
编辑:
根据Luigi的建议:
scala> def longestCommonPrefix(a: String, b: String): String = {
| var same = true
| var i = 0
| while(same && i < math.min(a.length, b.length)) {
| if(a.charAt(i) != b.charAt(i)) {
| same = false
| } else {
| i += 1
| }
| }
| a.substring(0, i)
| }
longestCommonPrefix: (a: String, b: String)String
scala> longestCommonPrefix("helloworld", "hellohell")
res68: String = hello
答案 5 :(得分:0)
获取任意数量字符串的公共前缀:
def commonPrefix (strs: Seq[String]): String = {
var i = 0;
strs(0).takeWhile { ch => strs.forall(_(i) == ch) && {i += 1; true}} mkString
}
答案 6 :(得分:0)
def commonPrefix(strings: String*): String = {
val refString = strings.map(s => (s, s.length())).minBy { case (string, length) => length }._1
var i = 0
while (i < refString.length) {
if (!strings.forall(_(i) == refString(i))) return refString.substring(0, i)
i += 1
}
return refString
}
答案 7 :(得分:0)
根据每个OP请求,下面是一个简单的最佳快速的“功能样式”实现。
此实现与任何手写的可变命令式样式一样快(因为它是尾部递归的)。
def takeCommonPrefix(string1: String, string2: String): String = {
if (string1.nonEmpty && string2.nonEmpty) {
val (shorter, longer) =
if (string1.length < string2.length) (string1, string2)
else (string2, string1)
@scala.annotation.tailrec
def recursive(shorterIndex: Int = 0): String =
if (shorterIndex == shorter.length)
shorter
else
if (shorter(shorterIndex) != longer(shorterIndex))
shorter.take(shorterIndex)
else
recursive(shorterIndex + 1)
recursive()
}
else
""
}
作为奖励,如果您想要公用前缀,那么很有可能迫在眉睫。
def takeCommonSuffix(string1: String, string2: String): String = {
if (string1.nonEmpty && string2.nonEmpty) {
val (shorter, longer) =
if (string1.length < string2.length) (string1, string2)
else (string2, string1)
val longerOffset =
longer.length - shorter.length
@scala.annotation.tailrec
def recursive(shorterIndex: Int = shorter.length - 1): String =
if (shorterIndex == -1)
shorter
else
if (shorter(shorterIndex) != longer(shorterIndex + longerOffset))
shorter.takeRight(shorter.length - shorterIndex - 1)
else
recursive(shorterIndex - 1)
recursive()
}
else
""
}