Exemple:
[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 caractère?
Je préfère utiliser quelque chose comme:
asdf = "[12,23,987,43" asdf [0] = '' p asdf # >> "12, 23 987,43 "
Je cherche toujours le moyen le plus rapide et le 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
Courir 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 une autre réponse 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 résulte en:
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 en 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 résulte en:
# >> 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 effectué une recherche/remplacement, gsub
doit rechercher d'éventuelles correspondances supplémentaires avant de pouvoir déterminer si elle est terminée. sub
ne fait qu'un et termine. Considérez gsub
comme si c'était un minimum de deux appels sub
.
De plus, il est important de se rappeler que gsub
et sub
peuvent également être handicapés par des expressions rationnelles mal écrites qui correspondent beaucoup plus lentement qu'une recherche de sous-chaîne. Si possible, ancrez l'expression rationnelle pour en tirer le maximum de vitesse. Il y a des réponses ici sur Stack Overflow qui démontrent qu'il est donc préférable de chercher si vous voulez plus d'informations.
Semblable à la réponse de Pablo ci-dessus, mais un nettoyant d'ombre:
str[1..-1]
Renverra le tableau de 1 au dernier caractère.
'Hello World'[1..-1]
=> "Ello World"
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.
Je préfère ça:
str = "[12,23,987,43"
puts str[1..-1]
>> 12,23,987,43
Si vous voulez toujours supprimer les crochets principaux:
"[12,23,987,43".gsub(/^\[/, "")
Si vous souhaitez simplement supprimer le premier caractère et que vous savez qu'il ne fera pas partie d'un jeu de caractères multi-octets:
"[12,23,987,43"[1..-1]
ou
"[12,23,987,43".slice(1..-1)
À partir de 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"
N.B. vous pouvez également l'utiliser pour supprimer des éléments de 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 référence de Tin Man, cela semble assez rapide aussi (sous les deux dernières entrées delete_p
et delete_p!
). Ne ( pas tout à fait ajoute les faves précédentes à la vitesse, bien que ce soit 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)
Alternative inefficace:
str.reverse.chop.reverse
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 à un le premier caractère de la chaîne.
Merci à @ the-tin-man pour avoir établi les critères!
Hélas, je n'aime pas vraiment l'une 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émantiques/clairs sur ce qui se passe ([1..-1]
: "Euh, une plage allant de 1 à négatif 1? Yearg? "), ou ils sont lents ou longs à écrire (.gsub
, .length
).
Ce que nous essayons de faire est un "décalage" (dans le langage Array), mais nous renvoyons les caractères restants plutôt que ce qui a été déplacé. Utilisons notre Ruby pour rendre cela possible avec des chaînes! Nous pouvons utiliser l'opération rapide crochet, mais lui donner un bon nom et prendre un argument pour spécifier combien nous voulons chompez à l'avant:
class String
def eat!(how_many = 1)
self.replace self[how_many..-1]
end
end
Mais nous pouvons faire plus avec cette opération de support rapide mais difficile à manier. Pendant que nous y sommes, pour être complets, écrivons un #shift
et #first
pour String (pourquoi Array devrait-il avoir tout le fun‽‽), en prenant un argument pour spécifier le nombre de caractères que nous voulons supprimer 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, nous avons maintenant un moyen clair de tirer les caractères du début d'une chaîne, avec une méthode compatible avec Array#first
et Array#shift
(qui devrait être vraiment une méthode bang ??). Et nous pouvons aussi facilement obtenir la chaîne modifiée avec #eat!
. Hm, devrions-nous partager notre nouveau pouvoir eat!
ing 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!
Moyen facile:
str = "[12,23,987,43"
removed = str[1..str.length]
Manière impressionnante:
class String
def reverse_chop()
self[1..self.length]
end
end
"[12,23,987,43".reverse_chop()
(Remarque: préférez la solution de facilité :))
str = "[12,23,987,43"
str[0] = ""
list = [1,2,3,4] list.drop (1)
# => [2,3,4]
La liste supprime un ou plusieurs éléments au début du tableau, ne modifie pas le tableau et renvoie le tableau lui-même à la place de l'élément déposé.
class String
def bye_felicia()
felicia = self.strip[0] #first char, not first space.
self.sub(felicia, '')
end
end
Utiliser regex:
str = 'string'
n = 1 #to remove first n characters
str[/.{#{str.size-n}}\z/] #=> "tring"
Je trouve une solution intéressante à être str.delete(str[0])
pour sa lisibilité, bien que je ne puisse pas attester de ses performances.