Comment vérifier si une chaîne contient une sous-chaîne en Ruby


731

J'ai une variable chaîne avec du contenu:

varMessage =   
            "hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n"


            "/my/name/is/balaji.so\n"
            "call::myFunction(int const&)\n"
            "void::secondFunction(char const&)\n"
             .
             .
             .
            "this/is/last/line/liobrary.so"

Dans la chaîne, je dois trouver une sous-chaîne:

"hi/thsid/sdfhsjdf/dfjsd/sdjfsdn\n"

"/my/name/is/balaji.so\n"
"call::myFunction(int const&)\n"

Comment le trouver? J'ai besoin de déterminer si la sous-chaîne est présente ou non.



Voir stackoverflow.com/a/3878656/128421 pour une ventilation des différentes façons de procéder.
The Tin Man

Réponses:


1366

Vous pouvez utiliser la include?méthode:

my_string = "abcdefg"
if my_string.include? "cde"
   puts "String includes 'cde'"
end

103
N'oubliez pas que include?c'est sensible à la casse. Donc, si my_stringdans l'exemple ci-dessus serait quelque chose comme "abcDefg"(avec une majuscule D), include?("cde")reviendrait false. Vous voudrez peut-être faire un downcase()avant d'appeler include?().
phortx

4
Inclure seul n'est pas idéal car il peut lancer une NoMethodError si nil test = nil test.include? ("Test") NoMethodError: méthode non définie `include? ' pour nil: NilClass doit toujours convertir la valeur incluse dans la valeur attendue: - test.to_s.include? ("test")
Gary

@ Gary vous conseille si votre objectif est de minimiser les exceptions soulevées dans cette partie du code. Ce n'est pas toujours le meilleur objectif. Généralement, si vous attendez une chaîne à ce stade du code et qu'une valeur est nulle à la place, cela implique que quelque chose d'inattendu s'est produit et qu'une exception levée est appropriée. Si l'existence d'un zéro ici est inattendue, l'utilisation to_smasquera le problème et augmentera la distance entre la source et la détection du problème, ce qui rendra le débogage plus difficile.
Luke Griffiths

88

Si la casse n'est pas pertinente, alors une expression régulière insensible à la casse est une bonne solution:

'aBcDe' =~ /bcd/i  # evaluates as true

Cela fonctionnera également pour les chaînes multi-lignes.

Voir la classe Regexp de Ruby pour plus d'informations.


11
Si vous comparez avec l'entrée utilisateur et utilisez cette technique, n'oubliez pas d'utiliser Regexp.escapesur la chaîne. Pour la plupart des cas d'utilisation, some_str.include? substr.downcase()devrait fonctionner plus rapidement et être plus lisible.
Jack

4
L'utilisation d'une expression régulière de cette façon ne sera pas nécessairement plus rapide que l'utilisation 'aBcDe'.downcase.include?('bcd'). Les regex ont leur raison d'être mais ne les utilisent pas lorsque les méthodes intégrées sont plus rapides. L'analyse comparative avec les données réelles testées peut en révéler beaucoup.
le Tin Man

3
Cela n'évalue PAS comme vrai. Il évalue à 1, ce qui n'est pas vrai.
slindsey3000

2
!! ('aBcDe' = ~ / bcd / i) sera évalué à vrai ou faux. Utilisez le !! idiome
slindsey3000

2
sinon, utilisez match? pour renvoyer un booléen:/bcd/i.match?('aBcDe')
ferrell_io

45

Vous pouvez également le faire ...

my_string = "Hello world"

if my_string["Hello"]
  puts 'It has "Hello"'
else
  puts 'No "Hello" found'
end

# => 'It has "Hello"'

Cet exemple utilise la #[]méthode String de Ruby .


2
C'est une astuce intéressante que je n'ai jamais vue auparavant. Mais #include?c'est quand même un peu plus rapide.
Scott Schupbach

4
#include?ne fonctionne pas lorsque vous travaillez avec des phrases avec des espaces à l'intérieur car #includedivise la phrase en mots, puis utilise les mots comme des valeurs de tableau distinctes. Cela fonctionne parfaitement pour les phrases. +1
luissimo

Voir la []méthode String de Ruby pour plus d'informations.
The Tin Man

32

Développant la réponse de Clint Pachl:

La correspondance d' nilexpressions régulières dans Ruby revient lorsque l'expression ne correspond pas. Dans ce cas, il retourne l'index du caractère où la correspondance se produit. Par exemple:

"foobar" =~ /bar/  # returns 3
"foobar" =~ /foo/  # returns 0
"foobar" =~ /zzz/  # returns nil

Il est important de noter que dans Ruby uniquement nilet que l'expression booléenne est falsefausse. Tout le reste, y compris un tableau vide, un hachage vide ou le nombre entier 0, est évalué comme vrai.

C'est pourquoi l' /foo/exemple ci-dessus fonctionne et pourquoi.

if "string" =~ /regex/

fonctionne comme prévu, n'entrant dans la partie «vraie» du ifbloc que si une correspondance s'est produite.


21

Un idiome plus succinct que la réponse acceptée ci-dessus qui est disponible dans Rails (à partir de 3.1.0 et supérieur) est .in?:

my_string = "abcdefg"
if "cde".in? my_string
  puts "'cde' is in the String."
  puts "i.e. String includes 'cde'"
end

Je pense aussi que c'est plus lisible.

Consultez la in?documentation pour plus d'informations.

Notez à nouveau qu'il n'est disponible que dans Rails , et non en Ruby pur.


2
Cela repose sur des rails, le PO a demandé une solution rubis
dft

2
C'est vrai, bien qu'une proportion importante de développeurs Ruby utilisent Rails, j'ai pensé que cela pourrait être une solution préférée pour certains en raison de sa clarté et de sa brièveté.
stwr667

1
Voir stackoverflow.com/a/4239625/128421 . Il est dans Rails, mais est facilement accessible à partir de Ruby normal en utilisant les extensions de base de support actif de Rails qui permettent une sélection aisée de petits groupes de méthodes telles que seulement in?.
The Tin Man

Corrigez @theTinMan. "cde".in? my_stringen rendements Rubis purs NoMethodError. Mais avec require 'active_support/core_ext/object/inclusion'cela fonctionne, qui peut être chargé soit à partir de Rails lui-même, soit à partir des extensions de base Active Support Core .
stwr667

16

Voie ternaire

my_string.include?('ahr') ? (puts 'String includes ahr') : (puts 'String does not include ahr')

OU

puts (my_string.include?('ahr') ? 'String includes ahr' : 'String not includes ahr')

11

Vous pouvez utiliser la méthode String Element Reference qui est[]

À l'intérieur du []peut être une sous-chaîne littérale, un index ou une expression régulière:

> s='abcdefg'
=> "abcdefg"
> s['a']
=> "a"
> s['z']
=> nil

Puisque nilest fonctionnellement identique à falseet que toute sous-chaîne renvoyée l' []est, truevous pouvez utiliser la logique comme si vous utilisiez la méthode .include?:

0> if s[sub_s]
1>    puts "\"#{s}\" has \"#{sub_s}\""
1> else 
1*    puts "\"#{s}\" does not have \"#{sub_s}\""
1> end
"abcdefg" has "abc"

0> if s[sub_s]
1>    puts "\"#{s}\" has \"#{sub_s}\""
1> else 
1*    puts "\"#{s}\" does not have \"#{sub_s}\""
1> end
"abcdefg" does not have "xyz" 

Assurez-vous simplement de ne pas confondre un index avec une sous-chaîne:

> '123456790'[8]    # integer is eighth element, or '0'
=> "0"              # would test as 'true' in Ruby
> '123456790'['8']  
=> nil              # correct

Vous pouvez également utiliser une expression régulière:

> s[/A/i]
=> "a"
> s[/A/]
=> nil

2
c'est phénoménal
Craig

3

Comment vérifier si une chaîne contient une sous-chaîne en Ruby?

Lorsque vous dites «vérifier», je suppose que vous souhaitez renvoyer un booléen, auquel cas vous pouvez l'utiliser String#match?. match?accepte les chaînes ou les expressions régulières comme premier paramètre, si c'est le premier, il est automatiquement converti en expression régulière. Votre cas d'utilisation serait donc:

str = 'string'
str.match? 'strings' #=> false
str.match? 'string'  #=> true
str.match? 'strin'   #=> true
str.match? 'trin'    #=> true
str.match? 'tri'     #=> true

String#match?a l'avantage supplémentaire d'un deuxième argument facultatif qui spécifie un index à partir duquel rechercher la chaîne. Par défaut, il est défini sur 0.

str.match? 'tri',0   #=> true
str.match? 'tri',1   #=> true
str.match? 'tri',2   #=> false

2
user_input = gets.chomp
user_input.downcase!

if user_input.include?('substring')
  # Do something
end

Cela vous aidera à vérifier si la chaîne contient ou non une sous-chaîne

puts "Enter a string"
user_input = gets.chomp  # Ex: Tommy
user_input.downcase!    #  tommy


if user_input.include?('s')
    puts "Found"
else
    puts "Not found"
end
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.