เอาสตริงย่อยออกจากสตริง


194

ฉันแค่สงสัยว่ามีวิธีใดที่จะลบสายจากสายอื่นหรือไม่ บางสิ่งเช่นนี้

class String
  def remove(s)
    self[s.length, self.length - s.length]
  end
end

คำตอบ:


263

คุณสามารถใช้วิธีการแบ่ง:

a = "foobar"
a.slice! "foo"
=> "foo"
a
=> "bar"

มีไม่ใช่ '!' รุ่นเช่นกัน ข้อมูลเพิ่มเติมสามารถดูได้ในเอกสารเกี่ยวกับรุ่นอื่นเช่นกัน: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21


1
สง่างามมาก! นอกจากนี้คุณยังสามารถใช้[]s สำหรับรุ่นที่ไม่ใช่ผลกำไร
Matheus Moreira

65
สิ่งนี้มีผลข้างเคียงที่ไม่ดีในการคืนข้อความที่ถูกลบ (หรือค้นหาข้อความ) โชคไม่ดีที่ผูกพันกับผลของการลบ
Mike

10
คุณจะส่งคืนสตริงที่แบ่งส่วนและไม่ส่งผลกระทบต่อต้นฉบับได้อย่างไร? ตัวอย่างเช่นถ้าฉันมี "hello world" ฉันต้องการแบ่ง "hello" และส่งกลับเฉพาะส่วน "โลก" โดยไม่ต้องแก้ไขวัตถุสตริงเดิม?
jhabbott

14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
เออร์เนสต์

7
@bcackerman - deleteไม่ทำงานเพราะจะลบตัวละครทุกตัวที่คุณผ่าน:'hello world'.delete('hello') #=> ' wrd'
เป็นสนิมเมื่อ

165

วิธีการเกี่ยวกับstr.gsub("subString", "") ตรวจสอบทับทิมหมอ


38
subจะเหมาะสมกว่าgsubเนื่องจาก OP ต้องการเพียงลบสตริงย่อยจากจุดเริ่มต้นของสตริงไม่ใช่ทั้งหมดผ่านสตริง (ดูที่โค้ดตัวอย่างของเขา) และการใช้ regex เช่นนี้จะดีกว่า: str.sub(/^subString/, '')- เพราะทำให้มั่นใจได้ว่าสตริงย่อยจะถูกลบออกจากจุดเริ่มต้นเท่านั้น
Alex D

@AlexD การใช้ regex จะดีกว่า แต่มันอันตรายถ้าเราไม่แน่ใจว่าsubStringจะไม่มีตัวอักษรพิเศษ regex
David Moles

@DavidMoles ในกรณี/^subString/นี้เป็นตัวอักษรดังนั้นเราจึงมั่นใจได้ว่ามันจะไม่รวม metacharacters หากคุณกำลังแทนบางสายอื่น ๆ เข้าไปใน regex /#{Regexp.escape(str)}/คุณสามารถทำสิ่งนี้:
Alex D

ในคำตอบใช่ แต่ไม่ใช่ในคำถามของ OP ขอบคุณสำหรับตัวชี้ถึงRegexp.escape()แม้ว่า
David Moles

106

หากเป็นจุดสิ้นสุดของสตริงคุณสามารถใช้chomp:

"hello".chomp("llo")     #=> "he"

ถ้าการแสดงออกเป็น a.chomp ("llo"), chomp! แม่นยำยิ่งขึ้น
เฟอร์นันโดกอนซาเลซซานเชซ

1
นี่สะอาดกว่าชิ้น! เพราะไม่มีผลข้างเคียง
Ardee Aram

5
หากเป็นจากจุดเริ่มต้นของสตริงคุณสามารถใช้chompร่วมกับreverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe

45

หากคุณมีสตริงเป้าหมายเพียงครั้งเดียวคุณสามารถใช้:

str[target] = ''

หรือ

str.sub(target, '')

หากคุณมีการใช้เป้าหมายหลายครั้ง:

str.gsub(target, '')

ตัวอย่างเช่น

asdf = 'foo bar'
asdf['bar'] = ''
asdf #=> "foo "

asdf = 'foo bar'
asdf.sub('bar', '') #=> "foo "
asdf = asdf + asdf #=> "foo barfoo bar"
asdf.gsub('bar', '') #=> "foo foo "

หากคุณต้องการที่จะทำในสถานที่แทนใช้"!"รุ่นและgsub!sub!


2
ทับทิมคือความสนุก! สนุกกับการดูสิ่งต่างๆเช่น:asdf['bar'] = ''
Peter Butkovic

1
ฉันจะไม่เรียกสิ่งนั้นว่า "สนุก" - ไม่ใช่เรื่องง่าย
Jmoney38

31

หากคุณใช้ Rails ก็มีเช่นremoveกัน

เช่นอัตราผลตอบแทน"Testmessage".remove("message")"Test"

คำเตือน: วิธีนี้จะลบสิ่งที่เกิดขึ้นทั้งหมด


1
นี่ไม่ใช่คำตอบของ Vanilla Ruby แต่คำตอบที่ยอมรับไม่ใช่สิ่งที่คนส่วนใหญ่มองหา น่าเสียดายที่sliceวิธีการไม่ส่งคืนส่วนของสตริงที่ถูกแบ่งออก แต่จะส่งคืน "มีด"
Dylan Pierce

1
@DylanPierce ก็สวยง่ายต่อการใช้ฟังก์ชั่นที่ไม่ว่าการใช้slice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
เบนเน็ตต์ Talpers

1
อ่าใช่แล้วการพูดปดเป็นสิ่งที่รูบี้ปรับเปลี่ยนตัวแปรที่มีอยู่ ขอบคุณ @BennettTalpers
Dylan Pierce

27

ทับทิม 2.5+

หากสตริงย่อยของคุณอยู่ที่จุดเริ่มต้นของในตอนท้ายของสตริงแล้ว Ruby 2.5 ได้แนะนำวิธีการนี้:

  • delete_prefixสำหรับการลบสตริงย่อยจากจุดเริ่มต้นของสตริง
  • delete_suffixสำหรับการลบซับสตริงออกจากจุดสิ้นสุดของสตริง


1

หากฉันตีความถูกต้องคำถามนี้ดูเหมือนจะถามถึงการดำเนินการลบ (-) ระหว่างสตริงนั่นคือตรงกันข้ามกับการดำเนินการบวก (+) ในตัว (การต่อข้อมูล)

ไม่เหมือนกับคำตอบก่อนหน้านี้ฉันพยายามกำหนดการดำเนินการที่ต้องปฏิบัติตามคุณสมบัติ:

หาก c = a + b จากนั้น c - a = b และ c - b = a

เราต้องการเมธอด Ruby ในตัวเพียงสามตัวเท่านั้น

'abracadabra'.partition('abra').values_at(0,2).join == 'cadabra'.

ฉันจะไม่อธิบายวิธีการทำงานเพราะสามารถเข้าใจวิธีใช้งานได้ครั้งละหนึ่งวิธี

นี่คือหลักฐานของรหัสแนวคิด:

# minus_string.rb
class String
  def -(str)
    partition(str).values_at(0,2).join
  end
end

# Add the following code and issue 'ruby minus_string.rb' in the console to test
require 'minitest/autorun'

class MinusString_Test < MiniTest::Test

  A,B,C='abra','cadabra','abracadabra'

  def test_C_eq_A_plus_B
    assert C == A + B
  end

  def test_C_minus_A_eq_B
    assert C - A == B
  end

  def test_C_minus_B_eq_A
    assert C - B == A
  end

end

คำแนะนำสุดท้ายหนึ่งคำหากคุณใช้ Ruby รุ่นล่าสุด (> = 2.0): ใช้การปรับแต่งแทนการใช้โปรแกรมปรับปรุงสตริงเหมือนในตัวอย่างก่อนหน้า

มันง่ายเหมือน:

module MinusString
  refine String do
    def -(str)
      partition(str).values_at(0,2).join
    end
  end
end

และเพิ่มusing MinusStringก่อนบล็อกที่คุณต้องการ


+1 สำหรับแนวคิดของการปรับแต่ง ในขณะที่คลาส String ของการปะแก้ลิงอาจเป็น overkill สำหรับกรณีการใช้งานนี้บางครั้งเราจำเป็นต้องทำสิ่งที่ลิง - แก้ไขและแนวคิดของการปรับแต่งจริงๆส่องที่มัน
wondersz1

-2

นี่คือสิ่งที่ฉันจะทำ

2.2.1 :015 > class String; def remove!(start_index, end_index) (end_index - start_index + 1).times{ self.slice! start_index }; self end; end;
2.2.1 :016 >   "idliketodeleteHEREallthewaytoHEREplease".remove! 14, 32
 => "idliketodeleteplease" 
2.2.1 :017 > ":)".remove! 1,1
 => ":" 
2.2.1 :018 > "ohnoe!".remove! 2,4
 => "oh!" 

จัดรูปแบบในหลายบรรทัด:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end

-7
def replaceslug
  slug = "" + name
    @replacements = [
      [ "," , ""],
      [ "\\?" , ""],
      [ " " , "-"],
      [ "'" , "-"],
      [ "Ç" , "c"],
      [ "Ş" , "s"],
      [ "İ" , "i"],
      [ "I" , "i"],
      [ "Ü" , "u"],
      [ "Ö" , "o"],
      [ "Ğ" , "g"],
      [ "ç" , "c"],
      [ "ş" , "s"],
      [ "ı" , "i"],
      [ "ü" , "u"],
      [ "ö" , "o"],
      [ "ğ" , "g"],
    ]
  @replacements.each do |pair|
    slug.gsub!(pair[0], pair[1])
  end
  self.slug = slug.downcase
end

1
ทำไมลงคะแนนเสียงมากมาย? คุณทำอะไรผิด .. อาจจะกว้างเกินไป
zee

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