Eliminar la subcadena de la cadena

193

¿Me pregunto si hay algún método para eliminar una cadena de otra cadena? Algo como esto:

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

Respuestas:

263

Puedes usar el método de corte:

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

hay un no '!' versión también. También se puede ver más información en la documentación sobre otras versiones: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21

Pete
fuente
1
¡Muy elegante! También puede usar []s para la versión no explosiva.
Matheus Moreira
65
Esto tiene un efecto secundario negativo al devolver el texto eliminado (o el texto buscado). Lamentable por encadenar el resultado de la eliminación.
Mike
10
¿Cómo devuelve la cadena cortada y no afecta el original? Por ejemplo, si tengo "hola mundo", quiero cortar "hola" y devolver solo la parte "mundo", sin modificar el objeto de cadena original.
jhabbott
14
@ Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ernest
77
@bcackerman - deleteno funcionaría, ya que elimina todos los caracteres que pasas:'hello world'.delete('hello') #=> ' wrd'
oxidado
165

¿Qué tal si str.gsub("subString", "") echas un vistazo al Ruby Doc?

Piyush Mattoo
fuente
38
subsería más apropiado que gsub, ya que el OP solo quiere eliminar la subcadena desde el comienzo de la cadena, no todo a través de la cadena (mira su código de muestra). Y usar una expresión regular, como esta, sería mejor: str.sub(/^subString/, '')- porque asegura que la subcadena definitivamente se eliminará solo desde el principio.
Alex D
@AlexD Usar una expresión regular sería mejor, pero es peligroso si no podemos estar seguros de subStringque no incluye ningún carácter especial de expresión regular.
David Moles
@DavidMoles, en este caso, /^subString/es un literal, por lo que podemos estar muy seguros de que no incluye metacaracteres. Si está sustituyendo alguna otra cadena en una expresión regular, usted puede hacer esto: /#{Regexp.escape(str)}/.
Alex D
En la respuesta, sí, pero no en la pregunta del OP. Gracias por el puntero a Regexp.escape(), sin embargo.
David Moles
106

Si es el final de la cadena, también puede usar chomp:

"hello".chomp("llo")     #=> "he"
Esperando a Dev ...
fuente
si la expresión era a.chomp ("llo"), chomp! Es más preciso.
Fernando González Sánchez
1
Esto es más limpio que cortar, ya que no tiene efectos secundarios.
Ardee Aram
55
Si es desde el principio de la cadena, también se puede usar chompen combinación con reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe
45

Si solo tiene una aparición de la cadena de destino, puede usar:

str[target] = ''

o

str.sub(target, '')

Si tiene múltiples ocurrencias de uso objetivo:

str.gsub(target, '')

Por ejemplo:

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 "

Si necesita hacer sustituciones en el lugar, use las "!"versiones de gsub!y sub!.

el hombre de hojalata
fuente
2
ruby es divertido! realmente disfruto viendo cosas como:asdf['bar'] = ''
Peter Butkovic
1
No lo llamaría "divertido", quizás no intuitivo.
Jmoney38
31

Si está utilizando Rails también hay remove.

Por ejemplo, "Testmessage".remove("message")rendimientos "Test".

Advertencia: este método elimina todas las ocurrencias

Edwardmp
fuente
1
Esta no es una respuesta vainilla de Ruby, pero la respuesta aceptada no es exactamente lo que la mayoría de la gente está buscando. Lamentablemente, el slicemétodo no devuelve la porción de la cuerda que se ha cortado, devuelve el "cuchillo"
Dylan Pierce
1
@DylanPierce es bastante fácil implementar una función que lo hace usandoslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers
1
Ah, es cierto, explotar es cómo Ruby modifica la variable existente. Gracias @BennettTalpers
Dylan Pierce
26

Ruby 2.5+

Si su subcadena está al principio o al final de una cadena, Ruby 2.5 ha introducido los métodos para esto:

  • delete_prefix para eliminar una subcadena desde el comienzo de la cadena
  • delete_suffix para eliminar una subcadena del final de la cadena
Igor Drozdov
fuente
1

Si estoy interpretando bien, esta pregunta parece pedir algo así como una operación menos (-) entre cadenas, es decir, lo opuesto a la operación incorporada más (+) (concatenación).

A diferencia de las respuestas anteriores, estoy tratando de definir una operación que deba obedecer la propiedad:

SI c = a + b ENTONCES c - a = b Y c - b = a

Solo necesitamos tres métodos de Ruby integrados para lograr esto:

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

No explicaré cómo funciona porque se puede entender fácilmente ejecutando un método a la vez.

Aquí hay un código de prueba de concepto:

# 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

Un último consejo si está utilizando una versión reciente de Ruby (> = 2.0): use Refinamientos lugar de Cadenas de parches de mono como en el ejemplo anterior.

Es tan fácil como:

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

y agregue using MinusStringantes de los bloques donde lo necesite.

Claudio Floreani
fuente
+1 para los conceptos de refinamientos. Si bien la clase String de parches de mono es probablemente una exageración para este caso de uso, a veces tenemos que parchear cosas y el concepto de refinamientos realmente brilla.
wondersz1
-2

esto es lo que haría

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

Formateado en múltiples líneas:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end
JayTarka
fuente
-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
fuente
1
¿Por qué tantos votos negativos? qué hiciste mal ... demasiado amplio quizás
zee
El OP no solicitó eliminar, Öpor ejemplo.
Iulian Onofrei