วิธีการตรวจสอบว่าสตริงมีสตริงย่อยในทับทิมหรือไม่


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/…
Andrew Grimm

ดูstackoverflow.com/a/3878656/128421เพื่อดูรายละเอียดของวิธีการต่างๆ
ชายดีบุก

คำตอบ:


1365

คุณสามารถใช้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?()
phortx

4
รวมถึงมันเป็นของตัวเองไม่เหมาะเพราะมันสามารถโยน NoMethodError ถ้า nil test = nil test.include? ("test") NoMethodError: วิธีที่ไม่ได้กำหนด `รวม? ' สำหรับ nil: NilClass ควรแปลงค่าที่รวมอยู่ในค่าที่คาดไว้เสมอ: - test.to_s.include? ("test")
Gary

คำแนะนำของ @ Gary เก็บหากเป้าหมายของคุณคือลดข้อยกเว้นที่เกิดขึ้นในส่วนนี้ของรหัส นั่นไม่ใช่เป้าหมายที่ดีที่สุดเสมอไป โดยทั่วไปถ้าคุณคาดว่าสตริง ณ จุดนี้ในรหัสและค่าเป็นศูนย์แทนนั่นหมายถึงสิ่งที่ไม่คาดคิดเกิดขึ้นและข้อยกเว้นที่ถูกยกขึ้นมีความเหมาะสม หากไม่มีศูนย์ที่นี่อย่างไม่คาดคิดการใช้to_sจะซ่อนปัญหาและเพิ่มระยะห่างระหว่างแหล่งที่มากับการตรวจพบปัญหาทำให้ยากต่อการตรวจแก้จุดบกพร่อง
ลุคกริฟฟิ ธ

88

ถ้า case ไม่เกี่ยวข้องดังนั้นนิพจน์ทั่วไปที่ไม่สนใจตัวพิมพ์เล็กและใหญ่เป็นทางออกที่ดี:

'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?ก็ยังเร็วกว่าเล็กน้อย
Scott Schupbach

4
#include?ไม่ทำงานเมื่อคุณทำงานกับประโยคที่มีช่องว่างภายในเพราะ#includeแบ่งประโยคเป็นคำและใช้คำนั้นเป็นค่าอาร์เรย์ที่แยกจากกัน มันทำงานได้อย่างสมบูรณ์แบบสำหรับประโยค +1
luissimo

ดู[]วิธีการของ Ruby's String สำหรับข้อมูลเพิ่มเติม
ชายดีบุก

32

ขยายคำตอบของ Clint Pachl:

การจับคู่ Regex ใน Ruby ส่งคืนnilเมื่อนิพจน์ไม่ตรงกัน เมื่อใดก็จะส่งกลับดัชนีของตัวละครที่ตรงกับที่เกิดขึ้น ตัวอย่างเช่น:

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

สิ่งสำคัญคือให้สังเกตว่าใน Ruby เท่านั้นnilและนิพจน์บูลีนfalseประเมินว่าเป็นเท็จ ทุกอย่างรวมถึง Array ว่างเปล่า Hash ที่ว่างเปล่าหรือ Integer 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
สิ่งนี้ขึ้นอยู่กับรางรถไฟ OP ขอวิธีแก้ปัญหาทับทิม
dft

2
ถูกต้องถึงแม้ว่าจะมีนักพัฒนาทับทิมส่วนใหญ่ที่ใช้ Rails อยู่ แต่ฉันคิดว่านี่อาจเป็นทางออกที่ดีสำหรับบางคนเนื่องจากความชัดเจนและความกะทัดรัด
stwr667

1
ดูstackoverflow.com/a/4239625/128421 มันอยู่ใน Rails แต่สามารถเข้าถึงได้ง่ายจาก Ruby ปกติโดยใช้ส่วนขยายหลักสนับสนุนการใช้งานของ Rails ซึ่งช่วยให้สามารถเลือกวิธีการกลุ่มเล็ก ๆ เช่นเชอร์รี่ได้อย่างin?ง่ายดาย
ชายดีบุก

ถูกต้อง @theTinMan ในอัตราผลตอบแทนทับทิมบริสุทธิ์"cde".in? my_string NoMethodErrorแต่ด้วยrequire 'active_support/core_ext/object/inclusion'การทำงานซึ่งสามารถโหลดได้ทั้งจากทางรถไฟเองหรือจากการตัดลงใช้งานส่วนขยายการสนับสนุนหลัก
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

คุณสามารถใช้วิธีการอ้างอิงองค์ประกอบสตริงซึ่งเป็น[]

ภายใน[]สามารถเป็นสตริงย่อยตัวอักษรดัชนีหรือ regex:

> 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

คุณยังสามารถใช้ regex:

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

2
นี่เป็นปรากฎการณ์
Craig

3

วิธีการตรวจสอบว่าสตริงมีสตริงย่อยในทับทิมหรือไม่

เมื่อคุณพูดว่า 'ตรวจสอบ' String#match?ผมถือว่าคุณต้องการบูลกลับมาในกรณีที่คุณอาจจะใช้ match?ยอมรับสตริงหรือ regexes เป็นพารามิเตอร์ตัวแรกหากเป็นแบบดั้งเดิมมันจะถูกแปลงเป็น regex โดยอัตโนมัติ ดังนั้นกรณีการใช้งานของคุณจะเป็น:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.