Як перевірити, чи містить рядок підрядку в Ruby


731

У мене є змінна рядок із вмістом:

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"

У рядку я повинен знайти підрядку:

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

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

Як я можу його знайти? Мені потрібно визначити, присутній чи ні підряд.


3
Питання, пов’язані з цим: stackoverflow.com/questions/3876246/…
Ендрю Грімм

Дивіться stackoverflow.com/a/3878656/128421, щоб отримати докладні відомості про різні способи.
Олов'яний чоловік

Відповіді:


1364

Можна використовувати include?метод:

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

102
Пам'ятайте, що include?це обгрунтовано. Тож якби my_stringв прикладі вище було щось на зразок "abcDefg"(з великої літери D), include?("cde")повернеться false. Можливо, ви захочете зробити downcase()перед тим, як дзвонити include?().
фортекс

4
Включити його самостійно не ідеально, оскільки він може кинути NoMethodError, якщо nil test = nil test.include? ("Test") NoMethodError: не визначений метод `включати? ' для nil: NilClass завжди повинен перетворювати включене значення до очікуваного значення: - test.to_s.include? ("test")
Gary

@ Пора Gary справедлива, якщо ваша мета - мінімізувати винятки, порушені в цій частині коду. Це не завжди найкраща мета. Як правило, якщо ви очікуєте, що в цій точці коду є рядок, а натомість значення є нульовим, це означає, що сталося щось несподіване, і виняток, що піднімається, є доцільним. Якщо існування нуля тут несподіване, використання to_sприховає проблему та збільшить відстань між джерелом та виявленням проблеми, ускладнюючи налагодження.
Люк Гріффітс

88

Якщо випадок не має значення, правильне висловлення, що не враховує регістр, є хорошим рішенням:

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

Це також буде працювати для багаторядкових рядків.

Додаткову інформацію див. У класі Regexp Ruby .


11
Якщо ви співпадаєте з введенням користувача та використовуєте цю техніку, не забудьте використовувати Regexp.escapeв рядку. У більшості випадків використання some_str.include? substr.downcase()має працювати швидше і читати.
Джек

4
Використання цього регулярного виразу не обов'язково буде швидшим, ніж використання 'aBcDe'.downcase.include?('bcd'). Regex має своє призначення, але не використовуйте їх, коли вбудовані методи швидші. Бенчмаркинг фактичних даних, які тестуються, може виявити багато.
Олов'яний чоловік

3
Це НЕ оцінюється як істинне. Він оцінює до 1, що не відповідає дійсності.
slindsey3000

2
!! ('aBcDe' = ~ / bcd / i) буде оцінено як істинне або хибне. Використовувати !! ідіома
slindsey3000

2
альтернативно, використовувати матч? повернути булевий:/bcd/i.match?('aBcDe')
ferrell_io

45

Ви також можете це зробити ...

my_string = "Hello world"

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

# => 'It has "Hello"'

У цьому прикладі використовується #[]метод Рубін Стринг .


2
Це акуратний трюк, якого я не бачив раніше. Але #include?все-таки трохи швидше.
Скотт Шупбах

4
#include?не працює, коли ви працюєте з реченнями з пробілами всередині, оскільки #includeрозділяє речення на слова, а потім використовує слова як окремі значення масиву. Це ідеально підходить для пропозицій. +1
luissimo

Додаткову інформацію див. У []методі Рубінового рядка .
Олов'яний чоловік

32

Розгортання відповіді Клінта Пакла:

Збіг Regex у Ruby повертається, nilколи вираз не збігається. Після цього він повертає індекс символу, де відбувається збіг. Наприклад:

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

Важливо зауважити, що лише у Ruby nilі булевий вираз falseоцінюється як хибне. Все інше, включаючи порожній масив, порожній хеш або цілий 0, оцінюється як істинне.

Ось чому /foo/приклад вище працює, і чому.

if "string" =~ /regex/

працює, як очікувалося, вводячи "справжню" частину ifблоку, лише якщо відбулося збіг.


21

Більш лаконічна ідіома, ніж прийнята вище відповідь, доступна в Rails (від 3.1.0 і вище), це .in?:

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

Я також думаю, що це читабельніше.

Для in?отримання додаткової інформації див документацію.

Зауважте ще раз, що він доступний лише в Rails , а не в чистому Ruby.


2
Це спирається на рейки, ОП попросило рішення про рубін
dft

2
Це правильно, хоча оскільки значна частина розробників Ruby використовують Rails, я вважав, що це може бути кращим рішенням для деяких через його чіткість та стислість.
stwr667

1
Дивіться stackoverflow.com/a/4239625/128421 . Він знаходиться в Rails, але до нього легко дістатися з звичайного Ruby, використовуючи Rails ' Active Support Core Extension, що дозволяє легко вибирати вишні для невеликих груп таких методів, як тільки in?.
Олов'яний чоловік

Правильно @theTinMan. "cde".in? my_stringв чистому врожаї Рубі NoMethodError. Але require 'active_support/core_ext/object/inclusion'це працює, яке можна завантажувати або з самих Rails , або зі скороченого розширення Active Support Core .
stwr667

16

Трійковий шлях

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

АБО

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

11

Ви можете скористатися методом довідкового елемента рядка, який є[]

Всередині []може бути або буквальна підрядка, індекс, або регулярний вираз:

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

Оскільки nilфункціонально те саме, що falseі будь-яка підрядка, повернута звідти [], trueви можете використовувати логіку, як якщо б ви використовували метод .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" 

Просто переконайтеся, що ви не плутаєте індекс із підрядком:

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

Ви також можете використовувати регулярний вираз:

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

2
це феноменально
Крейг

3

Як перевірити, чи містить рядок підрядку в Ruby?

Коли ви говорите "перевірити", я припускаю, що ви хочете повернути булевий випадок, в якому випадку ви можете використовувати String#match?. match?приймає рядки або регулярні вирази в якості свого першого параметра, якщо він є першим, то він автоматично перетворюється в регулярний вираз. Отже, вашим випадком використання буде:

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

String#match?має додаткову перевагу необов'язкового другого аргументу, який визначає індекс, з якого слід шукати рядок. За замовчуванням це встановлено на 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

Це допоможе вам перевірити, чи містить рядок підрядку чи ні

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.