可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How do I compare these two string :
val a = "fit bit versa"
val b = "fitbit"
another example
val a = "go pro hero 6"
val b = "gopro"
another example
val a = "hero go pro 6"
val b = "gopro"
another example
val a = "hero 6 go pro"
val b = "gopro"
I want to get "true" for the above comparisons but not here:
val a = "vegan protein powder"
val b = "vega"
This should be false.
Currently I am doing:
def matchPattern(a:String, b: String):String=
{
val dd = a.split(" ")
val result = dd.map(_.toLowerCase())
if(result contains b.toLowerCase) true
else false
}
This works for last case but not the rest.
Any suggestion ?
回答1:
Here's one approach using sliding(i)
, where i
ranges from 2 to word-count in a
, to assemble a list of all possible concatenated adjacent words. It is then checked to see whether b
exactly matches any of the elements in the list, as shown below:
def matchPattern(a: String, b: String): Boolean = {
val words = a.toLowerCase.split("\\s+")
val concats = (2 to words.size).foldLeft(words)(
(acc, i) => acc ++ words.sliding(i).map(_.mkString)
)
concats contains b.toLowerCase
}
matchPattern("Hero go Pro 6", "gopro")
// res1: Boolean = true
matchPattern("Hero go Pro 6", "gopro6")
// res2: Boolean = true
matchPattern("Vegan protein powder", "vega")
// res3: Boolean = false
回答2:
Here's an approach using for/yield
that turned out similar to @leo-c approach. A for
is used to generate a sliding window of length i
from words
to return the original words and combinations.
def matchPattern(a:String, b: String): Boolean = {
val words = a.split(" ")
val combinations = words ++ (for(
i <- (2 to words.size);
acc <- words.sliding(i)
) yield acc).map(_.mkString)
combinations.contains(b)
}
Test cases:
val a = "fit bit versa"
val b = "fitbit"
val c = "go pro hero 6"
val d = "gopro"
val e = "hero go pro 6"
val f = "gopro"
//false
val g = "vegan protein powder"
val h = "vega"
val i = "foo gopro bar"
val j = "gopro"
val k = "foo go pro hero bar"
val l = "goprohero"
scala> matchPattern(a,b) && matchPattern(c,d) && matchPattern(e,f) && !matchPattern(g,h) && matchPattern(i,j) && matchPattern(k,l)
res175: Boolean = true
回答3:
I think this is a solution to your problem.
def matchPattern(a: String, b: String): Boolean =
a
.split("\\s+")
.tails
.flatMap(_.inits)
.exists(_.mkString("") == b)
This will check for any word or sequence of words in a
that exactly matches the word in b
. It will reject cases where b
is embedded in a longer word or sequence of words.
The split
call turns the string into a list of words.
The tails
call returns all the possible trailing sub-sequences of a list, and inits
returns all the leading sub-sequences. Combining the two generates all possible sub-sequences of the original list.
The exist
call joins the words together and compares them with the test word.
Note that tails
and inits
are lazy, so they will generate each solution to be tested in turn, and stop as soon as a solution is found. This is in contrast to the solutions using sliding
which create every possible combination before checking any of them.
回答4:
Something like this I guess (your requirements are incomplete, so I interpreted them to "match exactly the beginning portion of the given string, ending with whitespace or end of line, except maybe spaces).
@tailrec
def matchWords(input: Seq[Char], words: Seq[Char]): Boolean = (input, words) match {
case (Seq(), Seq() | Seq(' ', _*)) => true
case (Seq(), _) => false
case (Seq(a, tail@_*), Seq(b, rest@_*)) if a == b => matchWords(tail, rest)
case (_, Seq(' ', rest@_*)) => matchWords(input, rest)
case _ => false
}