J'ai une ficelle :
"foo (2 espaces) bar (3 espaces) baaar (6 espaces) fooo"
Comment supprimer les espaces répétitifs afin qu'il n'y ait pas plus d'un espace entre deux mots ?
J'ai une ficelle :
"foo (2 espaces) bar (3 espaces) baaar (6 espaces) fooo"
Comment supprimer les espaces répétitifs afin qu'il n'y ait pas plus d'un espace entre deux mots ?
Chaîne#squeeze comporte un paramètre facultatif permettant de spécifier les caractères à écraser.
irb> "asd asd asd asd".squeeze(" ")
=> "asd asd asd asd"
Attention : si vous l'appelez sans paramètre, TOUS les caractères répétés, et pas seulement les espaces, seront supprimés :
irb> 'aaa bbbb cccc 0000123'.squeeze
=> "a b c 0123"
Ce n'est pas vrai... il peut "endommager" la chaîne... l'exemple serait "50b2a6cc6d5a2fb4e7000006" où vous obtiendriez "50b2a6c6d5a2fb4e706".
+1 pour une façon amusante de procéder, mais -1 pour une suggestion inefficace par rapport à d'autres alternatives plus appropriées.
@zetetic. Merci. Cela prouve une fois de plus que le split/join n'est pas un moyen amusant ou inefficace, ( comme je l'ai toujours su ) que la substitution de regex.
Mise à jour du benchmark à partir de la réponse de @zetetic :
require 'benchmark'
include Benchmark
string = "foo bar bar baaar"
n = 1_000_000
bm(12) do |x|
x.report("gsub ") { n.times { string.gsub(/\s+/, " ") } }
x.report("squeeze(' ')") { n.times { string.squeeze(' ') } }
x.report("split/join") { n.times { string.split.join(" ") } }
end
Ce qui donne les valeurs suivantes lorsque je l'exécute sur mon bureau après l'avoir fait deux fois :
ruby test.rb; ruby test.rb
user system total real
gsub 6.060000 0.000000 6.060000 ( 6.061435)
squeeze(' ') 4.200000 0.010000 4.210000 ( 4.201619)
split/join 3.620000 0.000000 3.620000 ( 3.614499)
user system total real
gsub 6.020000 0.000000 6.020000 ( 6.023391)
squeeze(' ') 4.150000 0.010000 4.160000 ( 4.153204)
split/join 3.590000 0.000000 3.590000 ( 3.587590)
Le problème est que squeeze
supprime tout caractère répété, ce qui donne une chaîne de sortie différente et ne répond pas au besoin de l'OP. squeeze(' ')
répond aux besoins, mais ralentit son fonctionnement.
string.squeeze
=> "fo bar bar bar"
J'ai réfléchi à la façon dont la split.join
pourrait être plus rapide et il ne semblait pas que cela puisse être le cas pour les grandes chaînes, j'ai donc ajusté le point de référence pour voir quel serait l'effet des longues chaînes :
require 'benchmark'
include Benchmark
string = (["foo bar bar baaar"] * 10_000).join
puts "String length: #{ string.length } characters"
n = 100
bm(12) do |x|
x.report("gsub ") { n.times { string.gsub(/\s+/, " ") } }
x.report("squeeze(' ')") { n.times { string.squeeze(' ') } }
x.report("split/join") { n.times { string.split.join(" ") } }
end
ruby test.rb ; ruby test.rb
String length: 250000 characters
user system total real
gsub 2.570000 0.010000 2.580000 ( 2.576149)
squeeze(' ') 0.140000 0.000000 0.140000 ( 0.150298)
split/join 1.400000 0.010000 1.410000 ( 1.396078)
String length: 250000 characters
user system total real
gsub 2.570000 0.010000 2.580000 ( 2.573802)
squeeze(' ') 0.140000 0.000000 0.140000 ( 0.150384)
split/join 1.400000 0.010000 1.410000 ( 1.397748)
Les longues files d'attente font donc une grande différence.
Si vous utilisez gsub, alors gsub/ \s {2,}/, ' ') est légèrement plus rapide.
Pas vraiment. Voici une version du test de référence permettant de vérifier cette affirmation :
require 'benchmark'
include Benchmark
string = "foo bar bar baaar"
puts string.gsub(/\s+/, " ")
puts string.gsub(/\s{2,}/, ' ')
puts string.gsub(/\s\s+/, " ")
string = (["foo bar bar baaar"] * 10_000).join
puts "String length: #{ string.length } characters"
n = 100
bm(18) do |x|
x.report("gsub") { n.times { string.gsub(/\s+/, " ") } }
x.report('gsub/\s{2,}/, "")') { n.times { string.gsub(/\s{2,}/, ' ') } }
x.report("gsub2") { n.times { string.gsub(/\s\s+/, " ") } }
end
# >> foo bar bar baaar
# >> foo bar bar baaar
# >> foo bar bar baaar
# >> String length: 250000 characters
# >> user system total real
# >> gsub 1.380000 0.010000 1.390000 ( 1.381276)
# >> gsub/\s{2,}/, "") 1.590000 0.000000 1.590000 ( 1.609292)
# >> gsub2 1.050000 0.010000 1.060000 ( 1.051005)
Si vous voulez de la rapidité, utilisez gsub2
. squeeze(' ')
peut toujours tourner en rond autour d'un gsub
Cependant, la mise en œuvre de l'accord n'est pas encore achevée.
Note importante : il s'agit d'une réponse pour Ruby on Rails, pas pour Ruby tout court. (les deux Activesupport
y Facets
font partie de Rails
gemme)
Pour compléter les autres réponses, notez que [Activesupport][1] et [Facets][1] fournissent [String#squish][2] ([update] caveat : il supprime également les nouvelles lignes dans la chaîne) :
>> "foo bar bar baaar".squish
=> "foo bar bar baaar"
fonction [1] : http://www.rubydoc.info/docs/rails/2.3.8/ActiveSupport/CoreExtensions/String/Filters#squish-instance_method [2] : http://www.rubydoc.info/github/rubyworks/facets/String%3Asquish
Utiliser une expression régulière pour faire correspondre les espaces blancs répétitifs (\s+)
et le remplacer par un espace.
"foo bar foobar".gsub(/\s+/, ' ')
=> "foo bar foobar"
Cela correspond à tous les espaces blancs. Si vous souhaitez uniquement remplacer les espaces, utilisez / +/
au lieu de /\s+/
.
"foo bar \nfoobar".gsub(/ +/, ' ')
=> "foo bar \nfoobar"
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.
2 votes
Vous savez, il est facile de répondre à ce genre de question en passant en revue toutes les méthodes de String. Je recommande vivement de se familiariser avec la documentation des méthodes String, Array et Enumerable.
0 votes
Si vous ne savez pas par où commencer, consultez le site suivant http://ruby-doc.org/ puis cliquez sur le bouton API de base puis cliquez sur la classe String dans la colonne centrale supérieure.
1 votes
Pour la défense de l'OP, la suppression des espaces peut être réalisée de plusieurs façons, qui ne sont pas toutes les plus intuitives, en particulier lorsque vous regardez les résultats de l'analyse comparative.