201 votes

Quel est le moyen le plus simple de supprimer le premier caractère d'une chaîne de caractères ?

Ejemplo:

[12,23,987,43

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

1 votes

J'ai modifié ma réponse, il est donc possible de changer la réponse que vous avez choisie. Voyez si vous pouvez l'attribuer à la réponse de Jason Stirk car la sienne est la plus rapide et est très lisible.

3 votes

Utilisez str[1..-1], c'est le plus rapide selon les réponses ci-dessous.

1 votes

À partir de Ruby 2.5, vous pouvez utiliser delete_prefix y delete_prefix! - plus de détails ci-dessous . Je n'ai pas eu le temps de faire un benchmark, mais je le ferai bientôt !

317voto

Jason Stirk Points 1371

Similaire à la réponse de Pablo ci-dessus, mais un peu plus propre :

str[1..-1]

Renverra le tableau de 1 au dernier caractère.

'Hello World'[1..-1]
 => "ello World"

13 votes

+1 Jetez un coup d'œil aux résultats du benchmark que j'ai ajouté à ma réponse. Vous avez le temps d'exécution le plus rapide, et je pense que c'est très propre.

0 votes

Qu'en est-il des performances de str[1,] par rapport à ce qui précède ?

1 votes

@Bohr : str[1,] vous renvoie le 2ème caractère puisque la plage est 1:nil . Vous devez fournir la longueur réelle calculée, ou quelque chose de garanti comme étant supérieur à la longueur, par exemple, str[1,999999] (utilisez int_max bien sûr) pour obtenir la queue entière. [1..-1] est plus propre et probablement plus rapide, puisque vous n'avez pas besoin d'opérer sur la longueur manuellement (voir le [1..length] dans le benchmark)

248voto

the Tin Man Points 69148

Je préfère utiliser 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

Fonctionne 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 incorporer une réponse supplémentaire suggérée :

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

Ce qui a pour conséquence :

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 utilisant /^./ 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

Ce qui a pour conséquence :

# >> 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 un matériel plus rapide et une version plus récente 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 fait une recherche/remplacement, gsub doit vérifier s'il y a d'autres correspondances possibles avant de savoir s'il a terminé. sub n'en fait qu'une et termine. Pensez à gsub comme si c'était un minimum de deux sub appels.

En outre, il est important de se rappeler que gsub y sub peut également être handicapé par des expressions rationnelles mal écrites qui correspondent beaucoup plus lentement qu'une recherche par sous-chaîne. Si possible, ancrez la regex pour en tirer le maximum de vitesse. Il y a des réponses ici sur Stack Overflow qui démontrent cela, alors cherchez si vous voulez plus d'informations.

34 votes

Il est important de noter que cela ne fonctionne qu'en Ruby 1.9. En Ruby 1.8, cela supprimera le premier élément octet de la chaîne, pas le premier caractère, ce qui n'est pas ce que souhaite le PO.

0 votes

+1 : I toujours oubliez qu'à une position de chaîne de caractères, vous pouvez non seulement attribuer un caractère unique, mais aussi insérer une sous-chaîne. Merci !

0 votes

"[12,23,987,43".delete "["

55voto

balanv Points 3101

Nous pouvons utiliser la tranche pour ce faire :

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

Utilisation de slice! on peut supprimer n'importe quel caractère en spécifiant son index.

2 votes

Cet élégant slice!(0) devrait vraiment être la réponse choisie, car l'utilisation de asdf[0] = '' pour supprimer le premier caractère est ridicule (tout comme utiliser gsub avec regex et tirer sur une mouche avec un obusier).

1 votes

Bien que cela puisse sembler peu intuitif à première vue, []= ne nécessite pas autant de code C sous-jacent, alors que slice! nécessite un travail supplémentaire. Cela s'ajoute. L'argument pourrait être "Qu'est-ce qui est le plus lisible ?". Je trouve qu'utiliser []= lisible, mais je viens d'un milieu C --> Perl qui colore probablement ma pensée. Les développeurs Java penseraient probablement que c'est moins lisible. L'un ou l'autre est un moyen acceptable d'accomplir la tâche tant qu'il est facilement compréhensible et maintenable et qu'il ne charge pas indûment le CPU.

0 votes

Ok. Savez-vous comment nous pouvons mesurer si une fonction prend beaucoup de charge CPU dans le ROR ? Ou devrions-nous utiliser la différence de temps d'exécution en milli ou nanosecondes ?

18voto

user2576846 Points 11

Je préfère ça :

str = "[12,23,987,43"
puts str[1..-1]
>> 12,23,987,43

3 votes

Vous pouvez vérifier les autres réponses avant de les répéter. Cela a déjà été suggéré par stackoverflow.com/a/3614642/128421

14voto

Chris Heald Points 28814

Si vous voulez toujours enlever les crochets de tête :

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

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

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

o

"[12,23,987,43".slice(1..-1)

1 votes

J'utiliserais "[12,23,987,43".sub(/^\[+/, "") au lieu de gsub(/^\[/, "") . La première permet au moteur d'expressions rationnelles de trouver toutes les correspondances et de les remplacer en une seule action. Elle permet de multiplier par deux la vitesse d'exécution avec Ruby 1.9.3.

1 votes

Puisque nous avons affaire à des chaînes de caractères, cela devrait être gsub(/\A\[/, "") ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X