Remover substring da string

193

Eu estou apenas querendo saber se existe algum método para remover string de outra string? Algo assim:

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

Respostas:

263

Você pode usar o método de fatia:

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

existe um não '!' versão também. Mais informações podem ser vistas na documentação sobre outras versões: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21

Pete
fonte
1
Muito elegante! Você também pode usar []s para a versão non-bang.
Matheus Moreira
65
Isso tem um efeito colateral ruim de retornar o texto excluído (ou o texto pesquisado). Lamentável por encadear o resultado da exclusão.
Mike
10
Como você devolve a corda fatiada e não afeta o original? Por exemplo, se eu tiver "olá mundo", desejo dividir "olá" e retornar apenas a parte "mundo", sem modificar o objeto de string original?
jhabbott
14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ernest
7
@bcackerman - deletenão funcionaria, pois exclui todos os caracteres que você digita : #'hello world'.delete('hello') #=> ' wrd'
rusty
165

Que tal str.gsub("subString", "") Confira o Doc Ruby

Piyush Mattoo
fonte
38
subseria mais apropriado do que gsub, já que o OP deseja remover a substring desde o início da string, não toda a string (veja seu código de exemplo). E usar um regex, como este, seria melhor: str.sub(/^subString/, '')- porque garante que a substring será definitivamente removida apenas desde o início.
Alex D
@AlexD Usar um regex seria melhor, mas é perigoso se não tivermos certeza de subStringque não inclui nenhum caractere especial de regex.
David Moles
@DavidMoles, nesse caso, /^subString/é literal, portanto podemos ter certeza de que não inclui nenhum metacaractere. Se você estiver substituindo alguma outra string em uma regex, você pode fazer isso: /#{Regexp.escape(str)}/.
Alex D
Na resposta, sim, mas não na pergunta do OP. Obrigado pelo ponteiro para Regexp.escape(), no entanto.
David Moles
105

Se for o fim da cadeia, você também pode usar chomp:

"hello".chomp("llo")     #=> "he"
A aguardar Dev ...
fonte
se a expressão fosse a.chomp ("llo"), chomp! é mais preciso.
Fernando Gonzalez Sanchez
1
Isso é mais limpo que a fatia !, pois não tem efeitos colaterais.
Ardee Aram
5
Se é a partir do início da string, você também pode usar chompem combinação com reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe
45

Se você tiver apenas uma ocorrência da sequência de destino, poderá usar:

str[target] = ''

ou

str.sub(target, '')

Se você tiver várias ocorrências de uso de destino:

str.gsub(target, '')

Por exemplo:

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 "

Se você precisar fazer substituições no local, use as "!"versões de gsub!e sub!.

o homem de lata
fonte
2
Ruby é divertido! realmente gosto de ver coisas como:asdf['bar'] = ''
Peter Butkovic
1
Eu não chamaria isso de "divertido" - talvez não intuitivo.
Jmoney38 17/05/19
31

Se você estiver usando o Rails, também há remove.

Por exemplo, "Testmessage".remove("message")rendimentos "Test".

Aviso: este método remove todas as ocorrências

edwardmp
fonte
1
Esta não é uma resposta de baunilha Ruby, mas a resposta aceita não é exatamente o que a maioria das pessoas está procurando. Infelizmente, o slicemétodo não retorna a parte da cadeia de caracteres que é cortado, ele retorna a "faca"
Dylan Pierce
1
@DylanPierce é muito fácil de implementar uma função que faz isso usandoslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers
1
Ah, é isso mesmo, é como Ruby modifica a variável existente. Obrigado @BennettTalpers
Dylan Pierce
26

Ruby 2.5+

Se sua substring está no início de no final de uma string, o Ruby 2.5 introduziu os métodos para isso:

Igor Drozdov
fonte
1

Se estou interpretando corretamente, essa pergunta parece pedir algo como uma operação de menos (-) entre seqüências de caracteres, ou seja, o oposto da operação interna de mais (+) (concatenação).

Diferentemente das respostas anteriores, estou tentando definir uma operação que deve obedecer à propriedade:

Se c = a + b ENTÃO c - a = b AND c - b = a

Precisamos apenas de três métodos Ruby internos para conseguir isso:

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

Não vou explicar como funciona, porque pode ser facilmente entendido executando um método de cada vez.

Aqui está uma prova de código de conceito:

# 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

Um último conselho, se você estiver usando uma versão recente do Ruby (> = 2.0): use Refinements vez de String de correção de macacos, como no exemplo anterior.

É tão fácil quanto:

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

e adicione using MinusStringantes dos blocos onde você precisar.

Claudio Floreani
fonte
+1 para os conceitos de refinamentos. Embora a classe String de correção de macaco seja provavelmente um exagero para esse caso de uso, às vezes temos que corrigir coisas de macaco e o conceito de refinamentos realmente brilha.
wondersz1
-2

aqui está o que eu faria

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

Formatado em várias linhas:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end
JayTarka
fonte
-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
ilkay
fonte
1
Por que tantos votos negativos? o que você fez de errado .. muito amplo talvez
zee
O OP não pediu para remover, Öpor exemplo.
Iulian Onofrei