Edit: Ceci est une réponse mise à jour, en fonction des commentaires ci-dessous. J'ai laissé ma réponse originale en bas.
L'analyse d'une chaîne pour "deux mots consécutifs" est un peu difficile. Votre meilleure option est probablement d'utiliser la \b
ancre dans une expression régulière, ce qui signifie une « limite de mot »:
string_to_change = "a b c d"
matches = string_to_change.scan(/\b((\S+?)\b.*?\b(\S+?))\b/)
# => [["a b", "a", "b"], ["c d", "c", "d"]]
... Lorsque la première chaîne est le « match plein » (y compris les espaces ou la ponctuation), les autres sont les deux mots.
Décomposer que regex:
\b
signifie "limites de mot". J'ai placé un de chaque côté des deux cordes. Cette solution suppose que str1
et str2
sont tous les deux un seul mot. (S'ils contiennent des espaces, alors je ne sais pas quel comportement vous attendez?)
\S+?
signifie "un ou plusieurs caractères non blancs". (Correspondant de manière non-avare, il s'arrêtera donc à première limite de mot).
Vous pouvez ensuite supprimer chaque « match plein » de la chaîne, si la méthode retourne vrai pour les deux mots:
matches.each do |full_match, word1, word2|
string_to_change.gsub!(full_match, '') if my_function(word1, word2)
end
Une chose qui est pas représenté ici (vous ne l'avez pas spécifiez ceci bien dans votre question ...) était comment manipuler des ficelles contenant trois mots ou plus. Par exemple, considérer les points suivants:
"hello world this is a test"
Supposons que my_function(word1, word2)
retours true
seulement pour les paires: "world", "this"
et "hello", "is"
.
Mon code ci-dessus ne regarder les paires: "hello", "world"
, "this", "is"
et "a", "test"
. Mais peut-être il devrait en fait:
- Regardez tous paires de mots, à savoir tous les mots avec la gauche et côté droit.
- paires Suppression de mots à plusieurs reprises , à savoir après que la paire initiale:
"world this"
est retiré, la chaîne doit être re-numérisé puis "hello is"
doit également être retiré?
Si d'autres améliorations sont nécessaires, veuillez les expliquer clairement dans une nouvelle question (si vous avez du mal à résoudre le problème vous-même).
réponse originale:
str1 = "b"
str2 = "c"
string_to_change = "a b c d"
if my_function(str1, str2)
string_to_change.gsub!(/\b#{str1}\b\s+\b#{str2}\b/, "")
end
Décomposer que regex:
\b
signifie "limite de mot". J'ai placé un de chaque côté des deux cordes. Cette solution suppose que str1
et str2
sont tous les deux un seul mot. (Si elles contiennent des espaces, alors je ne sais pas quel comportement vous attendez?)
\s+
signifie "un ou plusieurs caractères d'espacement". Vous souhaiterez peut-être modifier ce paramètre pour autoriser d'autres signes de ponctuation, par exemple une virgule ou un point. Une solution entièrement générique à ce problème pourrait en fait être:
.
string_to_change.gsub!(/\b#{str1}\b.(\B.)*#{str2}\b/, "")
# Or equivalently:
string_to_change.gsub!(/\b#{str1}\b(.\B)*.#{str2}\b/, "")
.(\B.)*
est la collecte au lieu chaque caractère, un à la fois, toujours vérifier que ce n'est pas la première lettre d'un mot (à savoir on passe par une limite non-mot).
C'est une instruction 'if', pas une méthode. Oui, vous pouvez. –
(Tant que vous définissez d'abord la méthode 'my_function' et que vous la renvoyez' true') essayez d'exécuter ceci dans une console. Ça fonctionne bien. –
Merci, mais vous avez codé plusieurs choses dans votre solution. Je ne faisais que lister "b" et "c" comme exemple. Il y a un certain nombre de parametesr qui peuvent rendre ma fonction my_function (str1, str2) vraie. Et si on me donne juste une longue chaîne de texte?Comment puis-je faire fonctionner la logique alors? – Dave