Quel est le moyen le 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?

Je préfère en quelque sorte utiliser quelque chose comme:

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

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

Je cherche toujours 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 incorporer une autre réponse suggérée:

 require 'benchmark' N = 1_000_000 class Ssortingng 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 aboutit à:

 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 Ssortingng 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 aboutit à:

 # >> 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 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 effectué une recherche / remplacement, gsub doit rechercher d’éventuelles correspondances supplémentaires avant de savoir s’il est terminé. sub ne fait qu’un et se termine. Considérez gsub comme si c’était un minimum de deux sub appels.

De plus, il est important de se rappeler que gsub et sub peuvent aussi être gsub par des regex mal écrites qui correspondent beaucoup plus lentement à une recherche par sous-chaîne. Si possible, ancrer le regex pour en tirer le maximum de vitesse. Il y a des réponses ici sur le dépassement de stack démontrant que la recherche autour de vous si vous voulez plus d’information.

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

 str[1..-1] 

Reviendra le tableau de 1 au dernier caractère.

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

Nous pouvons utiliser la tranche pour faire ceci:

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

Utiliser la slice! nous pouvons supprimer n’importe quel caractère en spécifiant son index.

Si vous voulez toujours supprimer les parenthèses:

 "[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 multi-octets:

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

ou

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

je préfère ça

 srt = [12,23,987,43 p srt[1..-1] >> 12,23,987,43 

Alternative inefficace:

 str.reverse.chop.reverse 

Par exemple: a = “One Two Three”

 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 le premier caractère de la chaîne.

Depuis Ruby 2.5, vous pouvez utiliser delete_prefix ou delete_prefix! pour y parvenir de manière lisible.

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

Plus d’infos 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" 

NB: vous pouvez également l’utiliser pour supprimer des éléments à la fin d’une chaîne avec delete_suffix et delete_suffix!

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

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

Modifier:

En utilisant la configuration de delete_p Tin Man, cela semble assez rapide (sous les deux dernières entrées delete_p et delete_p! ). Ne joue pas les faveurs précédentes 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) 

Moyen facile:

 str = "[12,23,987,43" removed = str[1..str.length] 

Manière géniale:

 class Ssortingng def reverse_chop() self[1..self.length] end end "[12,23,987,43".reverse_chop() 

(Note: préférez le moyen facile :))

Merci à @ the-tin-man d’avoir assemblé les benchmarks!

Hélas, je n’aime vraiment aucune de ces solutions. Soit ils exigent une étape supplémentaire pour obtenir le résultat ( [0] = '' , .ssortingp! ) Ou ils ne sont pas très sémantiques / clairs sur ce qui se passe ( [1..-1] : “Um, une plage de 1 à négatif 1? Yearg? “), ou ils sont lents ou longs à écrire ( .gsub , .length ).

Ce que nous essayons, c’est un «changement» (en langage Array), mais en retournant les caractères restants, plutôt que ce qui a été décalé. Utilisons notre Ruby pour rendre cela possible avec des chaînes! Nous pouvons utiliser l’opération de support rapide, mais donnez-lui un bon nom et prenez un argument pour préciser combien nous voulons compenser:

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

Mais nous pouvons faire plus avec cette opération rapide mais peu maniable. Pendant que nous y sums, pour être complet, écrivons un #shift et #first pour Ssortingng (pourquoi Array devrait-il avoir tout le fun‽‽), en prenant un argument pour spécifier combien de caractères nous voulons supprimer du début:

 class Ssortingng 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 manière claire de tirer les caractères du Array#first d’une chaîne, avec une méthode 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 avec #eat! . Hm, devrions-nous partager notre nouveau eat! pouvoir 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!

 str = "[12,23,987,43" str[0] = "" 
 class Ssortingng def bye_felicia() felicia = self.ssortingp[0] #first char, not first space. self.sub(felicia, '') end end 

Utiliser regex:

 str = 'ssortingng' n = 1 #to remove first n characters str[/.{#{str.size-n}}\z/] #=> "sortingng" 

Je trouve une bonne solution pour être str.delete(str[0]) pour sa lisibilité, même si je ne peux pas attester de ses performances.

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

# => [2,3,4]

List supprime un ou plusieurs éléments du début du tableau, ne modifie pas le tableau et renvoie le tableau lui-même au lieu de l’élément supprimé.