Quelle est la façon la plus simple de supprimer le premier caractère d'une chaîne?

exemple:

[12,23,987,43

Quel est le moyen le plus rapide et le plus efficace pour supprimer le " [ ", en utilisant peut-être un chop() mais pour le premier caractère?

149
demandé sur the Tin Man 2010-09-01 05:13:50

15 réponses

j'ai une sorte de faveur en utilisant quelque chose comme:

asdf = "[12,23,987,43"
asdf[0] = '' 

p asdf
# >> "12,23,987,43"

je suis toujours à la recherche de la façon la plus rapide et la plus lisible de faire les choses:

require 'benchmark'

N = 1_000_000

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }

end

en cours d'Exécution sur mon Mac Pro:

1.9.3
              user     system      total        real
[0]       0.840000   0.000000   0.840000 (  0.847496)
sub       1.960000   0.010000   1.970000 (  1.962767)
gsub      4.350000   0.020000   4.370000 (  4.372801)
[1..-1]   0.710000   0.000000   0.710000 (  0.713366)
slice     1.020000   0.000000   1.020000 (  1.020336)
length    1.160000   0.000000   1.160000 (  1.157882)

mise à Jour pour intégrer encore une proposition de réponse:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }

  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

qui se traduit par:

2.1.2
              user     system      total        real
[0]       0.300000   0.000000   0.300000 (  0.295054)
sub       0.630000   0.000000   0.630000 (  0.631870)
gsub      2.090000   0.000000   2.090000 (  2.094368)
[1..-1]   0.230000   0.010000   0.240000 (  0.232846)
slice     0.320000   0.000000   0.320000 (  0.320714)
length    0.340000   0.000000   0.340000 (  0.341918)
eat!      0.460000   0.000000   0.460000 (  0.452724)
reverse   0.400000   0.000000   0.400000 (  0.399465)

Et un autre à l'aide de /^./ pour trouver le premier caractère:

require 'benchmark'

N = 1_000_000

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end

  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

puts RUBY_VERSION

STR = "[12,23,987,43"

Benchmark.bm(7) do |b|
  b.report('[0]') { N.times { "[12,23,987,43"[0] = '' } }
  b.report('[/^./]') { N.times { "[12,23,987,43"[/^./] = '' } }
  b.report('[/^\[/]') { N.times { "[12,23,987,43"[/^\[/] = '' } }
  b.report('sub+') { N.times { "[12,23,987,43".sub(/^\[+/, "") } }
  b.report('sub') { N.times { "[12,23,987,43".sub(/^\[/, "") } }
  b.report('gsub') { N.times { "[12,23,987,43".gsub(/^\[/, "") } }
  b.report('[1..-1]') { N.times { "[12,23,987,43"[1..-1] } }
  b.report('slice') { N.times { "[12,23,987,43".slice!(0) } }
  b.report('length') { N.times { "[12,23,987,43"[1..STR.length] } }
  b.report('eat!') { N.times { "[12,23,987,43".eat! } }
  b.report('reverse') { N.times { "[12,23,987,43".reverse.chop.reverse } }
end

qui se traduit par:

# >> 2.1.5
# >>               user     system      total        real
# >> [0]       0.270000   0.000000   0.270000 (  0.270165)
# >> [/^./]    0.430000   0.000000   0.430000 (  0.432417)
# >> [/^\[/]   0.460000   0.000000   0.460000 (  0.458221)
# >> sub+      0.590000   0.000000   0.590000 (  0.590284)
# >> sub       0.590000   0.000000   0.590000 (  0.596366)
# >> gsub      1.880000   0.010000   1.890000 (  1.885892)
# >> [1..-1]   0.230000   0.000000   0.230000 (  0.223045)
# >> slice     0.300000   0.000000   0.300000 (  0.299175)
# >> length    0.320000   0.000000   0.320000 (  0.325841)
# >> eat!      0.410000   0.000000   0.410000 (  0.409306)
# >> reverse   0.390000   0.000000   0.390000 (  0.393044)

voici une autre mise à jour sur le matériel plus rapide et une nouvelle version de Ruby:

2.3.1
              user     system      total        real
[0]       0.200000   0.000000   0.200000 (  0.204307)
[/^./]    0.390000   0.000000   0.390000 (  0.387527)
[/^\[/]   0.360000   0.000000   0.360000 (  0.360400)
sub+      0.490000   0.000000   0.490000 (  0.492083)
sub       0.480000   0.000000   0.480000 (  0.487862)
gsub      1.990000   0.000000   1.990000 (  1.988716)
[1..-1]   0.180000   0.000000   0.180000 (  0.181673)
slice     0.260000   0.000000   0.260000 (  0.266371)
length    0.270000   0.000000   0.270000 (  0.267651)
eat!      0.400000   0.010000   0.410000 (  0.398093)
reverse   0.340000   0.000000   0.340000 (  0.344077)

pourquoi gsub est-il si lent?

après avoir effectué une recherche/remplacer, gsub doit vérifiez si d'autres correspondances sont possibles avant de savoir si c'est terminé. sub ne fait qu'un et finit. Considérez gsub comme un minimum de deux appels sub .

aussi, il est important de se rappeler que gsub , et sub peuvent également être handicapés par regex mal écrit qui correspondent beaucoup plus lentement qu'une recherche sous-chaîne. Si possible, l'ancrage de la regex pour obtenir le plus de vitesse. Il y a des réponses ici sur le débordement de la pile ce qui démontre que si la recherche autour si vous voulez plus d'informations.

210
répondu the Tin Man 2016-11-15 22:52:00

semblable à la réponse de Pablo ci-dessus, mais un nettoyeur d'ombre:

str[1..-1]

renvoie le tableau de 1 au dernier caractère.

'Hello World'[1..-1]
 => "ello World"
266
répondu Jason Stirk 2010-09-01 02:25:35

nous pouvons utiliser slice pour faire ceci:

val = "abc"
 => "abc" 
val.slice!(0)
 => "a" 
val
 => "bc" 

en utilisant slice! nous pouvons supprimer n'importe quel caractère en spécifiant son index.

43
répondu balanv 2014-06-22 20:22:28

si vous voulez toujours supprimer les crochets avant:

"[12,23,987,43".gsub(/^\[/, "")

Si vous voulez simplement supprimer le premier caractère, et vous savez qu'il ne sera pas dans un jeu de caractères multioctets:

"[12,23,987,43"[1..-1]

ou

"[12,23,987,43".slice(1..-1)
14
répondu Chris Heald 2010-09-01 01:20:12

je préfère cette

srt = [12,23,987,43
p srt[1..-1]
>> 12,23,987,43
12
répondu henriquesuda 2016-01-10 03:00:17

alternative inefficace:

str.reverse.chop.reverse
6
répondu jaamun 2014-08-28 18:44:51

par exemple: a = "Un Deux Trois "

1.9.2-p290 > a = "One Two Three"
 => "One Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "ne Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "e Two Three" 

1.9.2-p290 > a = a[1..-1]
 => " Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "Two Three" 

1.9.2-p290 > a = a[1..-1]
 => "wo Three" 

De cette façon, vous pouvez supprimer un par un premier caractère de la chaîne.

4
répondu Rubyist 2012-04-09 06:21:19

à partir de Ruby 2.5 vous pouvez utiliser delete_prefix ou delete_prefix! pour réaliser ceci d'une manière lisible.

dans ce cas "[12,23,987,43".delete_prefix("[") .

plus d'informations ici:

https://blog.jetbrains.com/ruby/2017/10/10-new-features-in-ruby-2-5 /

https://bugs.ruby-lang.org/issues/12694

'invisible'.delete_prefix('in') #=> "visible"
'pink'.delete_prefix('in') #=> "pink"

N.B. vous pouvez aussi utilisez ceci pour supprimer des articles de la fin d'une chaîne de caractères avec delete_suffix et delete_suffix!

'worked'.delete_suffix('ed') #=> "work"
'medical'.delete_suffix('ed') #=> "medical"

https://bugs.ruby-lang.org/issues/13665

Edit:

en utilisant la configuration de référence de Tin Man, il semble assez rapide aussi (sous les deux dernières entrées delete_p et delete_p! ). Ne pas tout à fait pip de la précédente favoris pour la vitesse, mais est très lisible.

2.5.0
              user     system      total        real
[0]       0.174766   0.000489   0.175255 (  0.180207)
[/^./]    0.318038   0.000510   0.318548 (  0.323679)
[/^\[/]   0.372645   0.001134   0.373779 (  0.379029)
sub+      0.460295   0.001510   0.461805 (  0.467279)
sub       0.498351   0.001534   0.499885 (  0.505729)
gsub      1.669837   0.005141   1.674978 (  1.682853)
[1..-1]   0.199840   0.000976   0.200816 (  0.205889)
slice     0.279661   0.000859   0.280520 (  0.285661)
length    0.268362   0.000310   0.268672 (  0.273829)
eat!      0.341715   0.000524   0.342239 (  0.347097)
reverse   0.335301   0.000588   0.335889 (  0.340965)
delete_p  0.222297   0.000832   0.223129 (  0.228455)
delete_p!  0.225798   0.000747   0.226545 (  0.231745)
4
répondu SRack 2017-10-27 12:30:11

voie Facile:

str = "[12,23,987,43"

removed = str[1..str.length]

Génial": 151930920"

class String
  def reverse_chop()
    self[1..self.length]
  end
end

"[12,23,987,43".reverse_chop()

(Note: préférer la voie de la facilité :) )

3
répondu Pablo Fernandez 2010-09-01 01:17:52

merci à @The-tin-man d'avoir assemblé les benchmarks!

hélas, je n'aime pas vraiment aucune de ces solutions. Soit ils nécessitent une étape supplémentaire pour obtenir le résultat ( [0] = '' , .strip! ) ou ils ne sont pas très sémantique/clair sur ce qui se passe ( [1..-1] : "Um, une gamme de 1 à négatif 1? Yearg?"), ou ils sont lents ou longs à écrire ( .gsub , .length ).

ce que nous tentons est un "changement" (en Tableau jargon), mais en retournant les caractères restants, plutôt que ce qui a été décalé. Utilisons notre rubis pour rendre cela possible avec des cordes! Nous pouvons utiliser l'opération rapide bracket, mais lui donner une bonne réputation, et prendre un arg pour préciser combien nous voulons chomp hors de l'avant:

class String
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

mais il y a plus que nous pouvons faire avec cette opération rapide-mais-lourde des crochets. Pendant que nous y sommes, par souci d'exhaustivité, écrivons un #shift et #first pour chaîne de caractères (pourquoi Array devrait avoir tout le plaisir‽), en prenant un arg pour spécifier le nombre de caractères que nous voulons supprimer dès le début:

class String
  def first(how_many = 1)
    self[0...how_many]
  end

  def shift(how_many = 1)
    shifted = first(how_many)
    self.replace self[how_many..-1]
    shifted
  end
  alias_method :shift!, :shift
end

Ok, maintenant nous avons une bonne façon claire de tirer des caractères sur le devant d'une chaîne, avec une méthode qui est compatible avec Array#first et Array#shift (qui devrait vraiment être une méthode de bang??). Et nous pouvons facilement obtenir la chaîne modifiée ainsi avec #eat! . Devrions-nous partager notre nouveau eat! avec Array? Pourquoi pas!

class Array
  def eat!(how_many = 1)
    self.replace self[how_many..-1]
  end
end

maintenant nous pouvons:

> str = "[12,23,987,43" #=> "[12,23,987,43"
> str.eat!              #=> "12,23,987,43"
> str                   #=> "12,23,987,43"

> str.eat!(3)           #=> "23,987,43"
> str                   #=> "23,987,43"

> str.first(2)          #=> "23"
> str                   #=> "23,987,43"

> str.shift!(3)         #=> "23,"
> str                   #=> "987,43"

> arr = [1,2,3,4,5]     #=> [1, 2, 3, 4, 5] 
> arr.eat!              #=> [2, 3, 4, 5] 
> arr                   #=> [2, 3, 4, 5] 

c'est mieux!

3
répondu brookr 2013-11-05 07:51:40
str = "[12,23,987,43"

str[0] = ""
2
répondu Handcraftsman 2010-09-01 02:19:47
class String
  def bye_felicia()
    felicia = self.strip[0] #first char, not first space.
    self.sub(felicia, '')
  end
end
0
répondu Josh Brody 2016-01-10 09:36:06

utilisant regex:

str = 'string'
n = 1  #to remove first n characters

str[/.{#{str.size-n}}\z/] #=> "tring"
0
répondu Sagar Pandya 2017-06-18 14:06:33

je trouve une bonne solution d'être str.delete(str[0]) pour sa lisibilité, bien que je ne puisse pas attester de sa performance.

0
répondu zeitchef 2018-03-02 14:23:00

liste = [1,2,3,4] liste.drop (1)

# => [2,3,4]

Liste fait tomber un ou plusieurs éléments du début du tableau, ne mute pas le tableau, et renvoie le tableau lui-même à la place de l'élément abandonné.

0
répondu Aaron Henderson 2018-07-18 09:20:20