Jak sprawdzić, czy ciąg znaków zawiera podciąg w Ruby


731

Mam zmienną łańcuchową z zawartością:

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"

W ciągu muszę znaleźć podciąg:

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

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

Jak mogę to znaleźć? Muszę ustalić, czy podciąg jest obecny, czy nie.



Zobacz stackoverflow.com/a/3878656/128421, aby uzyskać zestawienie różnych sposobów wykonania tego.
Tin Man

Odpowiedzi:


1364

Możesz użyć include?metody:

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

102
Pamiętaj, że include?to rozróżnianie wielkości liter. Więc jeśli my_stringw powyższym przykładzie byłoby coś w stylu "abcDefg"(z dużymi literami D), include?("cde")wróciłoby false. Możesz zrobić to downcase()przed połączeniem include?().
phortx

4
Dołączenie samo w sobie nie jest idealne, ponieważ może wyrzucić NoMethodError, jeśli zero test = zero test.include? („Test”) NoMethodError: niezdefiniowana metoda „include?” dla zera: NilClass powinien zawsze konwertować dołączaną wartość na wartość oczekiwaną: - test.to_s.include? („test”)
Gary

@ Gary radzi, jeśli Twoim celem jest zminimalizowanie wyjątków zgłaszanych w tej części kodu. To nie zawsze jest najlepszy cel. Zasadniczo, jeśli oczekujesz łańcucha w tym punkcie kodu, a zamiast tego wartość jest równa zero, oznacza to, że wystąpiło coś nieoczekiwanego, a zgłoszony wyjątek jest odpowiedni. Jeśli istnienie zera tutaj jest nieoczekiwane, użycie to_sspowoduje ukrycie problemu i zwiększenie odległości między źródłem a wykryciem problemu, co utrudni debugowanie.
Luke Griffiths

88

Jeśli wielkość liter jest nieistotna, dobrym rozwiązaniem jest niewrażliwe na wielkość liter wyrażenie regularne :

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

Będzie to również działać w przypadku ciągów wieloliniowych.

Aby uzyskać więcej informacji, zobacz klasę Ruby's Regexp .


11
Jeśli dopasowujesz do danych wprowadzonych przez użytkownika i używasz tej techniki, pamiętaj, aby użyć Regexp.escapeciągu. W większości przypadków some_str.include? substr.downcase()powinien działać szybciej i być bardziej czytelny.
Jack

4
Używanie wyrażenia regularnego w ten sposób niekoniecznie będzie szybsze niż używanie 'aBcDe'.downcase.include?('bcd'). Regex ma swój cel, ale nie używaj ich, gdy wbudowane metody są szybsze. Benchmarking z faktycznie testowanymi danymi może wiele pokazać.
Tin Man

3
To NIE ocenia się jako prawda. Ocenia to 1, co nie jest prawdą.
slindsey3000,

2
!! ('aBcDe' = ~ / bcd / i) będzie miało wartość true lub false. Użyj !! idiom
slindsey3000,

2
alternatywnie użyć dopasowania? zwrócić wartość logiczną:/bcd/i.match?('aBcDe')
ferrell_io

45

Możesz także to zrobić ...

my_string = "Hello world"

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

# => 'It has "Hello"'

W tym przykładzie użyto #[]metody String Ruby .


2
To fajna sztuczka, której wcześniej nie widziałem. Ale #include?wciąż jest trochę szybszy.
Scott Schupbach,

4
#include?nie działa, gdy pracujesz ze zdaniami ze spacjami wewnątrz, ponieważ #includedzieli zdanie na słowa, a następnie używa słów jako osobnych wartości tablicowych. Działa to doskonale w przypadku zdań. +1
luissimo,

Aby []uzyskać więcej informacji, zobacz Metoda Ruby's String .
Tin Man

32

Rozwijając odpowiedź Clinta Pachla:

Dopasowywanie nilwyrażeń regularnych w Ruby zwraca, gdy wyrażenie nie pasuje. Kiedy to zrobi, zwraca indeks znaku, w którym ma miejsce dopasowanie. Na przykład:

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

Ważne jest, aby pamiętać, że tylko w języku Ruby nilwyrażenie boolowskie ma falsewartość false. Wszystko inne, w tym pusta tablica, pusta wartość skrótu lub liczba całkowita 0, ma wartość true.

Właśnie dlatego /foo/powyższy przykład działa i dlaczego.

if "string" =~ /regex/

działa zgodnie z oczekiwaniami, wpisując „prawdziwą” część ifbloku tylko w przypadku dopasowania.


21

Bardziej zwięzły idiom niż zaakceptowana powyżej odpowiedź dostępna w Railsach (od 3.1.0 i wyżej) to .in?:

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

Myślę też, że jest bardziej czytelny.

Więcej informacji znajduje się w in?dokumentacji.

Zauważ jeszcze raz, że jest dostępny tylko w Railsach , a nie w czystym Ruby.


2
To zależy od szyn, OP poprosił o rozwiązanie rubinowe
dft

2
Zgadza się, chociaż ponieważ znaczna część programistów Ruby używa Railsów, pomyślałem, że dla niektórych może to być preferowane rozwiązanie ze względu na przejrzystość i zwięzłość.
stwr667,

1
Zobacz stackoverflow.com/a/4239625/128421 . Jest w Railsach, ale jest łatwo dostępny ze zwykłego Ruby przy użyciu podstawowych rozszerzeń Active Support Rails, które umożliwiają łatwe wybieranie małych grup metod, takich jak tylko in?.
Tin Man

Prawidłowy @ theTinMan. "cde".in? my_stringw czystych plonach Ruby NoMethodError. Ale dzięki require 'active_support/core_ext/object/inclusion'temu działa, które mogą być ładowane albo z samego Railsa , albo z odciętych podstawowych rozszerzeń Active Support Core .
stwr667

16

Sposób trójskładnikowy

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

LUB

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

11

Możesz użyć metody String Element Reference , która jest[]

Wewnątrz []może znajdować się dosłowny podciąg, indeks lub wyrażenie regularne:

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

Ponieważ nilfunkcjonalnie jest taki sam, jak falsei każdy zwrócony podciąg []to truemożesz użyć logiki tak, jakbyś używał metody .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" 

Tylko upewnij się, że nie pomylisz indeksu z łańcuchem podrzędnym:

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

Możesz także użyć wyrażenia regularnego:

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

2
to jest fenomenalne
Craig,

3

Jak sprawdzić, czy ciąg znaków zawiera podciąg w Ruby?

Kiedy mówisz „sprawdź”, zakładam, że chcesz zwrócić wartość logiczną, w którym to przypadku możesz użyć String#match?. match?akceptuje ciągi lub wyrażenia regularne jako swój pierwszy parametr, jeśli jest to pierwszy parametr, wówczas jest automatycznie konwertowany na wyrażenie regularne. Twój przypadek użycia to:

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

String#match?ma dodatkową zaletę opcjonalnego drugiego argumentu, który określa indeks, z którego należy przeszukiwać ciąg. Domyślnie jest to ustawione na 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

Pomoże to sprawdzić, czy ciąg zawiera podciąg, czy nie

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.