Cách kiểm tra xem một chuỗi có chứa một chuỗi con trong Ruby không


731

Tôi có một biến chuỗi có nội dung:

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"

Trong chuỗi tôi phải tìm một chuỗi con:

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

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

Làm thế nào tôi có thể tìm thấy nó? Tôi cần xác định xem chuỗi con có mặt hay không.



Xem stackoverflow.com/a/3878656/128421 để biết chi tiết các cách khác nhau để làm điều này.
Tin Man

Câu trả lời:


1366

Bạn có thể sử dụng include?phương pháp:

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

103
Hãy nhớ rằng đó include?là trường hợp nhạy cảm. Vì vậy, nếu my_stringtrong ví dụ trên sẽ là một cái gì đó giống như "abcDefg"(với chữ hoa D), include?("cde")sẽ trở lại false. Bạn có thể muốn làm một downcase()trước khi gọi include?().
phortx

4
Bao gồm cả bản thân nó không lý tưởng vì nó có thể ném NoMethodError nếu nil test = nil test.include? ("Test") NoMethodError: phương thức không xác định `bao gồm? ' đối với nil: NilClass phải luôn chuyển đổi giá trị được bao gồm thành giá trị mong đợi: - test.to_s.include? ("test")
Gary

Lời khuyên của Gary giữ nếu mục tiêu của bạn là giảm thiểu các ngoại lệ được nêu trong phần này của mã. Đó không phải lúc nào cũng là mục tiêu tốt nhất. Nói chung, nếu bạn mong đợi một chuỗi tại thời điểm này trong mã và thay vào đó là một giá trị, điều đó ngụ ý điều gì đó bất ngờ đã xảy ra và một ngoại lệ được đưa ra là phù hợp. Nếu sự tồn tại của một con số không ở đây là bất ngờ, việc sử dụng to_ssẽ che giấu vấn đề và tăng khoảng cách giữa nguồn và phát hiện vấn đề, khiến việc gỡ lỗi trở nên khó khăn hơn.
Luke Griffiths

88

Nếu trường hợp không liên quan, thì biểu thức chính quy không phân biệt chữ hoa chữ thường là một giải pháp tốt:

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

Điều này cũng sẽ làm việc cho các chuỗi nhiều dòng.

Xem lớp Regapi của Ruby để biết thêm thông tin.


11
Nếu bạn khớp với đầu vào của người dùng và sử dụng kỹ thuật này, hãy nhớ sử dụng Regexp.escapetrên chuỗi. Đối với hầu hết các trường hợp sử dụng, some_str.include? substr.downcase()nên làm việc nhanh hơn và dễ đọc hơn.
Jack

4
Sử dụng biểu thức chính quy theo cách này không nhất thiết sẽ nhanh hơn sử dụng 'aBcDe'.downcase.include?('bcd'). Regex có mục đích của họ nhưng không sử dụng chúng khi các phương thức tích hợp nhanh hơn. Điểm chuẩn với dữ liệu thực tế đang được thử nghiệm có thể tiết lộ nhiều.
Tin Man

3
Điều này KHÔNG đánh giá là đúng. Nó đánh giá là 1 không đúng.
slindsey3000

2
!! ('aBcDe' = ~ / bcd / i) sẽ đánh giá là đúng hay sai. Sử dụng !! thành ngữ
slindsey3000

2
Cách khác, sử dụng khớp? để trả lại một boolean:/bcd/i.match?('aBcDe')
ferrell_io

45

Bạn cũng có thể làm điều này ...

my_string = "Hello world"

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

# => 'It has "Hello"'

Ví dụ này sử dụng #[]phương thức Chuỗi của Ruby .


2
Đây là một mẹo gọn gàng tôi chưa từng thấy trước đây. Nhưng #include?vẫn nhanh hơn một chút.
Scott Schupbach

4
#include?không hoạt động khi bạn đang làm việc với các câu có khoảng trắng bên trong vì #includechia câu trong các từ và sau đó sử dụng các từ làm giá trị mảng riêng biệt. Điều này hoạt động hoàn hảo cho câu. +1
luissimo

Xem []phương pháp Chuỗi của Ruby để biết thêm thông tin.
Tin Man

32

Mở rộng câu trả lời của Clint Pachl:

Kết hợp Regex trong Ruby trả về nilkhi biểu thức không khớp. Khi đó, nó trả về chỉ mục của nhân vật nơi trận đấu xảy ra. Ví dụ:

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

Điều quan trọng cần lưu ý là chỉ trong Ruby nilvà biểu thức boolean falseđánh giá là sai. Mọi thứ khác, bao gồm Mảng trống, Hash trống hoặc Số nguyên 0, đều đánh giá là đúng.

Đó là lý do tại sao /foo/ví dụ trên hoạt động, và tại sao.

if "string" =~ /regex/

hoạt động như mong đợi, chỉ nhập phần 'đúng' của ifkhối nếu trận đấu xảy ra.


21

Một thành ngữ ngắn gọn hơn câu trả lời được chấp nhận ở trên có sẵn trong Rails (từ 3.1.0 trở lên) là .in?:

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

Tôi cũng nghĩ rằng nó dễ đọc hơn.

Xem in?tài liệu để biết thêm thông tin.

Lưu ý một lần nữa rằng nó chỉ có sẵn trong Rails chứ không phải Ruby thuần túy.


2
Điều này phụ thuộc vào đường ray, OP đã yêu cầu một giải pháp ruby
dft

2
Điều đó đúng, mặc dù vì một tỷ lệ đáng kể các nhà phát triển Ruby đang sử dụng Rails, tôi nghĩ rằng đây có thể là một giải pháp ưa thích đối với một số người vì sự rõ ràng và ngắn gọn của nó.
stwr667

1
Xem stackoverflow.com/a/4239425/128421 . Nó có trong Rails, nhưng có thể dễ dàng truy cập từ Ruby thông thường bằng cách sử dụng Tiện ích mở rộng lõi hỗ trợ hoạt động của Rails , cho phép dễ dàng chọn các nhóm phương thức nhỏ như chỉ in?.
Tin Man

Đúng @theTinMan. "cde".in? my_stringtrong sản lượng Ruby tinh khiết NoMethodError. Nhưng với require 'active_support/core_ext/object/inclusion'nó hoạt động, có thể được tải từ chính Rails hoặc từ Tiện ích mở rộng lõi hỗ trợ tích cực .
stwr667

16

Cách thức

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

HOẶC LÀ

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

11

Bạn có thể sử dụng phương thức String Element Reference[]

Bên trong []có thể là một chuỗi con theo nghĩa đen, một chỉ mục hoặc biểu thức chính quy:

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

Vì về mặt nilchức năng giống như falsevà bất kỳ chuỗi con nào được trả về []truebạn có thể sử dụng logic như thể bạn sử dụng phương thức .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" 

Chỉ cần đảm bảo rằng bạn không nhầm lẫn một chỉ mục với một chuỗi phụ:

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

Bạn cũng có thể sử dụng regex:

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

2
đây là một hiện tượng
Craig

3

Làm cách nào để kiểm tra xem một chuỗi có chứa một chuỗi con trong Ruby không?

Khi bạn nói 'kiểm tra', tôi giả sử bạn muốn trả lại boolean trong trường hợp bạn có thể sử dụng String#match?. match?chấp nhận chuỗi hoặc biểu thức chính là tham số đầu tiên của nó, nếu là tham số trước thì nó sẽ tự động được chuyển thành biểu thức chính. Vì vậy, trường hợp sử dụng của bạn sẽ là:

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

String#match?có thêm lợi ích của một đối số thứ hai tùy chọn chỉ định một chỉ mục để tìm kiếm chuỗi. Theo mặc định, điều này được đặt thành 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

Điều này sẽ giúp bạn kiểm tra xem chuỗi có chứa chuỗi con hay không

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.