Supprimer la sous-chaîne de la chaîne

193

Je me demande simplement s'il existe une méthode pour supprimer une chaîne d'une autre chaîne? Quelque chose comme ça:

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

Réponses:

263

Vous pouvez utiliser la méthode slice:

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

il y a un non '!' version aussi. Plus d'informations peuvent également être consultées dans la documentation des autres versions: http://www.ruby-doc.org/core/classes/String.html#method-i-slice-21

Pete
la source
1
Très élégant! Vous pouvez également utiliser []s pour la version non-bang.
Matheus Moreira
65
Cela a un mauvais effet secondaire de renvoyer le texte supprimé (ou le texte recherché). Malheureusement pour l'enchaînement sur le résultat de la suppression.
Mike
10
Comment renvoyez-vous la chaîne tranchée sans affecter l'original? Par exemple, si j'ai "bonjour le monde", je veux couper "bonjour" et retourner juste la partie "monde", sans modifier l'objet chaîne d'origine?
jhabbott
14
@Mike"foobar".tap{|s| s.slice!("foo")}.upcase
Ernest
7
@bcackerman - deletene fonctionnerait pas, car il supprime tous les personnages que vous passez:'hello world'.delete('hello') #=> ' wrd'
rouillé
165

Que diriez-vous de str.gsub("subString", "") consulter le Doc Ruby

Piyush Mattoo
la source
38
subserait plus approprié que gsub, puisque l'OP ne souhaite supprimer la sous-chaîne qu'au début de la chaîne, pas tout au long de la chaîne (regardez son exemple de code). Et l'utilisation d'une expression régulière, comme celle-ci, serait mieux: str.sub(/^subString/, '')- car elle garantit que la sous-chaîne ne sera définitivement supprimée que depuis le début.
Alex D
@AlexD Utiliser un regex serait mieux, mais c'est dangereux si nous ne pouvons pas être sûrs qu'il subStringn'inclut aucun caractère spécial regex.
David Moles
@DavidMoles, dans ce cas, /^subString/est un littéral, nous pouvons donc être sûrs qu'il ne contient aucun métacaractère. Si vous substituez une autre chaîne en une expression régulière, vous pouvez le faire: /#{Regexp.escape(str)}/.
Alex D
Dans la réponse, oui, mais pas dans la question du PO. Merci pour le pointeur vers Regexp.escape(), cependant.
David Moles
106

S'il s'agit de la fin de la chaîne, vous pouvez également utiliser chomp:

"hello".chomp("llo")     #=> "he"
En attendant Dev ...
la source
si l'expression était a.chomp ("llo"), chomp! est plus précis.
Fernando Gonzalez Sanchez
1
C'est plus propre que slice !, car cela n'a aucun effet secondaire.
Ardee Aram
5
Si c'est depuis le début de la chaîne, vous pouvez également l'utiliser chompen combinaison avec reverse:"hello".reverse.chomp("he".reverse).reverse #=> "llo"
amoebe
45

Si vous n'avez qu'une seule occurrence de la chaîne cible, vous pouvez utiliser:

str[target] = ''

ou

str.sub(target, '')

Si vous avez plusieurs occurrences d'utilisation cible:

str.gsub(target, '')

Par exemple:

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 vous devez effectuer des substitutions sur place, utilisez les "!"versions de gsub!et sub!.

l'homme d'étain
la source
2
rubis est amusant! aime vraiment voir des trucs comme:asdf['bar'] = ''
Peter Butkovic
1
Je n'appellerais pas cela "amusant" - non intuitif, peut-être.
Jmoney38
31

Si vous utilisez Rails, il y en a aussi remove.

Par exemple, les "Testmessage".remove("message")rendements "Test".

Attention: cette méthode supprime toutes les occurrences

edwardmp
la source
1
Ce n'est pas une réponse Ruby vanille, mais la réponse acceptée n'est pas tout à fait ce que la plupart des gens recherchent. Malheureusement, la sliceméthode ne renvoie pas la partie de la chaîne qui est tranchée, elle renvoie le "couteau"
Dylan Pierce
1
@DylanPierce, il est assez facile d'implémenter une fonction qui fait cela en utilisantslice! def gimme_the_slice(my_string, my_slice) my_string.slice!(my_slice) my_string
Bennett Talpers
1
Ah c'est vrai, bang-ifying est la façon dont Ruby modifie la variable existante. Merci @BennettTalpers
Dylan Pierce
26

Ruby 2.5+

Si votre sous-chaîne se trouve au début ou à la fin d'une chaîne, alors Ruby 2.5 a introduit les méthodes pour cela:

  • delete_prefix pour supprimer une sous-chaîne du début de la chaîne
  • delete_suffix pour supprimer une sous-chaîne de la fin de la chaîne
Igor Drozdov
la source
1

Si j'interprète correctement, cette question semble demander quelque chose comme une opération moins (-) entre les chaînes, c'est-à-dire l'opposé de l'opération plus (+) intégrée (concaténation).

Contrairement aux réponses précédentes, j'essaie de définir une telle opération qui doit obéir à la propriété:

SI c = a + b ALORS c - a = b ET c - b = a

Pour ce faire, nous n'avons besoin que de trois méthodes Ruby intégrées:

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

Je ne vais pas expliquer comment cela fonctionne, car il peut être facilement compris en exécutant une méthode à la fois.

Voici un code de preuve de concept:

# 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 dernier conseil si vous utilisez une version récente de Ruby (> = 2.0): utilisez des raffinements au lieu de singe-patching String comme dans l'exemple précédent.

C'est aussi simple que:

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

et ajoutez using MinusStringavant les blocs où vous en avez besoin.

Claudio Floreani
la source
+1 pour les concepts de raffinements. Bien que la classe String de patch de singe soit probablement une surpuissance pour ce cas d'utilisation, nous devons parfois faire des patchs de singe et le concept de raffinements brille vraiment.
wondersz1
-2

voici ce que je ferais

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

Formaté sur plusieurs lignes:

class String
    def remove!(start_index, end_index)
        (end_index - start_index + 1).times{ self.slice! start_index }
        self
    end 
end
JayTarka
la source
-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
la source
1
Pourquoi tant de votes négatifs? qu'avez-vous fait de mal .. trop large peut
zee
L'OP n'a pas demandé de retirer Öpar exemple.
Iulian Onofrei