5
votes

Comment comparer une chaîne avec une autre où l'une a un espace entre

Comment comparer ces deux chaînes:

def matchPattern(a:String, b: String):String=
{
      val dd = a.split(" ")
      val result = dd.map(_.toLowerCase())
      if(result contains b.toLowerCase) true 
      else false
}

un autre exemple

val a = "vegan protein powder"
val b = "vega"

un autre exemple

val a = "hero 6 go pro"
val b = "gopro"


6 commentaires

Qu'en est-il de val a = "foo gopro bar"; val b = "gopro" et val a = "foo go pro hero bar"; val b = "goprohero ?


Ouais ... tout cela devrait être vrai


\ bf \ s * i \ s * t \ s * b \ s * i \ s * t \ b et \ bg \ s * o \ s * p \ s * r \ s * o \ b et \ bv \ s * e \ s * g \ s * a \ b où les expressions rationnelles sont insensibles à la casse.


@sln Je pense que l'OP recherche une fonction générique matchPattern , pas quelques expressions régulières pour ce cas particulier. Ce serait bien si le PO expliquait plus clairement les règles du test.


@Tim - Evidemment, l'expression régulière est générée en mettant \ s * entre chaque caractère et en bookending avec les \ b .


@sln Le code pour cela peut ne pas être évident pour tout le monde, alors peut-être pourriez-vous le partager avec nous? Vous pouvez inclure une version curry de matchPattern qui est plus efficace lors de la vérification du même mot dans plusieurs chaînes.


4 Réponses :


-1
votes

Quelque chose comme ça je suppose (vos exigences sont incomplètes, donc je les ai interprétées comme "correspondant exactement à la partie de début de la chaîne donnée, se terminant par un espace ou une fin de ligne, sauf peut-être des espaces).

  @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
   }


0 commentaires

1
votes

Voici une approche utilisant glissant (i) , où i va de 2 au nombre de mots dans a , pour assembler une liste de tous les mots adjacents concaténés possibles. Il est ensuite vérifié pour voir si b correspond exactement à l'un des éléments de la liste, comme indiqué ci-dessous:

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


0 commentaires

0
votes

Je pense que c'est une solution à votre problème.

def matchPattern(a: String, b: String): Boolean =
  a
    .split("\\s+")
    .tails
    .flatMap(_.inits)
    .exists(_.mkString("") == b)

Cela vérifiera tout mot ou séquence de mots dans a qui correspond exactement au mot de b . Il rejettera les cas où b est incorporé dans un mot plus long ou une séquence de mots.

L'appel split transforme la chaîne en une liste de mots.

L'appel tails renvoie toutes les sous-séquences de fin possibles d'une liste, et inits renvoie toutes les sous-séquences de début. La combinaison des deux génère toutes les sous-séquences possibles de la liste d'origine.

L'appel exist joint les mots ensemble et les compare avec le mot de test.


Notez que tails et inits sont paresseux, ils vont donc générer chaque solution à tester à tour de rôle, et s'arrêter dès qu'une solution est trouvée. Cela contraste avec les solutions utilisant le glissant qui créent toutes les combinaisons possibles avant de les vérifier.


0 commentaires

0
votes

Voici une approche utilisant pour / yield qui s'est avérée similaire à l'approche @ leo-c. Un pour est utilisé pour générer une fenêtre glissante de longueur i à partir de mots pour renvoyer les mots et combinaisons d'origine.

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

Scénarios de test:

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)
} 


0 commentaires