Usuń podciąg z łańcucha


193

Zastanawiam się tylko, czy istnieje metoda usunięcia ciągu z innego ciągu? Coś takiego:

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

Odpowiedzi:


263

Możesz użyć metody wycinania:

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

istnieje non „!” również wersja. Więcej informacji można również znaleźć w dokumentacji innych wersji: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21


1
Bardzo elegancko! Możesz także użyć []s dla wersji innej niż Bang.
— Matheus Moreira,

65
Ma to zły efekt uboczny polegający na zwróceniu usuniętego tekstu (lub szukanego tekstu). Niefortunne dla powiązania wyniku usunięcia.
— Mike

10
Jak zwrócić pocięty łańcuch i nie wpływać na oryginał? Na przykład, jeśli mam „hello world”, chcę pokroić „hello” i zwrócić tylko część „world” bez modyfikowania oryginalnego obiektu string?
— jhabbott

14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
— Ernest,

7
@ backackerman - deletenie działa, ponieważ usuwa wszystkie znaki, które przekazujesz:'hello world'.delete('hello') #=> ' wrd'
— zardzewiały

165

Co powiesz na str.gsub("subString", "") sprawdzenie Ruby Doc


38
subbyłoby bardziej odpowiednie niż gsub, ponieważ OP chce tylko usunąć podłańcuch z początku łańcucha, nie przez cały łańcuch (spójrz na jego przykładowy kod). A użycie wyrażenia regularnego, takiego jak ten, byłoby lepsze: str.sub(/^subString/, '')- ponieważ zapewnia, że ​​podciąg będzie zdecydowanie usuwany od samego początku.
— Alex D

@AlexD Lepsze byłoby użycie wyrażenia regularnego, ale jest to niebezpieczne, jeśli nie możemy mieć pewności, subStringże nie zawiera żadnych znaków specjalnych wyrażenia regularnego.
— David Moles,

@DavidMoles w tym przypadku /^subString/jest dosłowny, więc możemy być pewni, że nie zawiera żadnych metaznaków. Jeśli podstawiając inny ciąg znaków w regex, można to zrobić: /#{Regexp.escape(str)}/.
— Alex D

W odpowiedzi tak, ale nie w pytaniu PO. Dzięki za wskaźnik do Regexp.escape().
— David Moles

106

Jeśli jest to koniec ciągu, możesz także użyć chomp:

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

jeśli wyrażenie to a.chomp („llo”), chomp! jest bardziej precyzyjny.
— Fernando Gonzalez Sanchez,

1
Jest to czystsze niż plasterek !, ponieważ nie ma żadnych skutków ubocznych.
— Ardee Aram

5
Jeśli jest od początku ciągu, możesz także użyć chompw połączeniu z reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
— amoebe

45

Jeśli masz tylko jedno wystąpienie ciągu docelowego, możesz użyć:

str[target] = ''

lub

str.sub(target, '')

Jeśli masz wiele wystąpień celu docelowego:

str.gsub(target, '')

Na przykład:

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 "

Jeśli chcesz dokonać zamiany w miejscu, użyj "!"wersji gsub!i sub!.


2
ruby jest fajny! naprawdę lubię oglądać rzeczy takie jak:asdf['bar'] = ''
— Peter Butkovic

1
Nie nazwałbym tego „zabawnym” - być może nieintuicyjnym.
— Jmoney38

31

Jeśli używasz Railsów, jest tam również remove.

Np . "Testmessage".remove("message")Plony "Test".

Ostrzeżenie: ta metoda usuwa wszystkie wystąpienia


1
To nie jest waniliowa odpowiedź Ruby, ale zaakceptowana odpowiedź nie jest tym, czego większość ludzi szuka. Niestety slicemetoda nie zwraca części ciętego sznurka, ale zwraca „nóż”
— Dylan Pierce

1
@DylanPierce jest dość łatwo zaimplementować funkcję, która robi to za pomocąslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
— Bennett Talpers

1
Ach, właśnie tak, Bang-ifying jest jak Ruby modyfikuje istniejącą zmienną. Dzięki @BennettTalpers
— Dylan Pierce

26

Ruby 2.5+

Jeśli twój podciąg znajduje się na początku łańcucha, to Ruby 2.5 wprowadził następujące metody:



1

Jeśli dobrze interpretuję, to pytanie wydaje się wymagać czegoś takiego jak operacja minus (-) między łańcuchami, tj. Przeciwieństwo wbudowanej operacji plus (+) (konkatenacja).

W przeciwieństwie do poprzednich odpowiedzi próbuję zdefiniować taką operację, która musi być zgodna z właściwością:

JEŚLI c = a + b NASTĘPNIE c - a = b ORAZ c - b = a

Potrzebujemy tylko trzech wbudowanych metod Ruby, aby to osiągnąć:

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

Nie wyjaśnię, jak to działa, ponieważ można to łatwo zrozumieć, uruchamiając jedną metodę na raz.

Oto kod dowodu koncepcji:

# 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

Ostatnie słowo porady, jeśli używasz najnowszej wersji Rubiego (> = 2.0): użyj Uściśleń zamiast ciągów małpich łatek, jak w poprzednim przykładzie.

Jest to tak proste jak:

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

i dodaj using MinusStringprzed blokami tam, gdzie jest to potrzebne.


+1 za koncepcje udoskonaleń. Podczas gdy łatanie małp klasy String jest prawdopodobnie przesadą w tym przypadku użycia, czasami musimy załatać małpy i koncepcja ulepszeń naprawdę na nich świeci.
— wondersz1

-2

oto co bym zrobił

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!" 

Sformatowany w wielu wierszach:

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
Po co tyle głosów? co zrobiłeś źle ... może zbyt szeroki
— zee

OP nie poprosił Öna przykład o usunięcie .
— Iulian Onofrei
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.