/ / Ruby supprime toutes les chaînes commençant par un caractère spécifique - ruby, gsub

Ruby supprime toutes les chaînes commençant par un caractère spécifique - ruby, gsub

Je voudrais supprimer toutes les sous-chaînes d'unchaîne qui commence par un signe dièse et se termine par un espace ou se trouve à la fin de la chaîne. J'ai une solution de travail, mais je me demande s’il existe une approche plus efficace (ou tout aussi efficace mais moins verbeuse).

Par exemple, je veux prendre "leo is #confused about #ruby #gsub" et le transformer en "#confused #ruby #gsub".

Voici ma solution pour l'instant, qui implique des tableaux et des soustractions.

strip_spaces = str.gsub(/s+/, " ").strip()
=> "leo is #confused about #ruby #gsub"
all_strings = strip_spaces.split(" ").to_a
=> ["leo", "is", "#confused", "about", "#ruby", "#gsub"]
non_hashtag_strings = strip_spaces.gsub(/(?:#(w+))/) {""}.split(" ").to_a
=> ["leo", "is", "about"]
hashtag_strings = (all_strings - non_hashtag_strings).join(" ")
=> "#confused #ruby #gsub"

Pour être honnête, maintenant que j'ai fini d'écrire ceciquestion, j'ai appris quelques choses par la recherche / expérimentation et devenir plus à l'aise avec cette approche de tableau. Mais je me demande encore si quelqu'un pourrait recommander une amélioration.

Réponses:

3 pour la réponse № 1

Je ferais quelque chose comme ça:

string = "leo is #confused about #ruby #gsub"
#=> "leo is #confused about #ruby #gsub"
string.split.select { |word| word.start_with?("#") }.join(" ")
#=> "#confused #ruby #gsub"

3 pour la réponse № 2

Regexp only solution

string = "leo is #confused about #ruby #gsub"
string.scan(/#w+/)
#  => ["#confused", "#ruby", "#gsub"]

Si vous vous attendez # signe à l'intérieur du mot, l'expression rationnelle est légèrement complexe:

string = "leo is #confused ab#out #ruby #gsub"
string.scan(/(?<=s)#w+/)
#  => ["#confused", "#ruby", "#gsub"]

2 pour la réponse № 3

Toujours plus de façons d'écorcher un chat

s = "leo is #confused about #ruby #gsub"
#sub all the words that do not start with a #
s.gsub(/(?<=^|s)#w+s?/,"")
#=> "#confused #ruby #gsub"
#split to Array and grab all the strings that start with #
s.split.grep(/A#/).join(" ")
#=> "#confused #ruby #gsub"
#split to Array and separate them into 2 groups
starts_with_hash,others = s.split.partition {|e| e.start_with?("#") }
#=>[["#confused", "#ruby", "#gsub"], ["leo", "is", "about"]]
starts_with_hash.join(" ")
#=> "#confused #ruby #gsub"

Analyse comparative de ces réponses et d'autres telles que fournies par fruity

require "fruity"

def split_start_with(s)
s.split.select {|e| e.start_with?("#")}.join(" ")
end

def with_scan(s)
s.scan(/#w+/).join(" ")
end

def with_gsub(s)
s.gsub(/(?<=^|s)#w+s?/,"")
end

def split_grep(s)
s.split.grep(/A#/).join(" ")
end

str = "This is a reasonable string #withhashtags where I want to #test multiple #stringparsing #methods for separating and joinging #hastagstrings together for #speed"

compare do
split_start_with_test {split_start_with(str)}
with_scan_test {with_scan(str)}
with_gsub_test {with_gsub(str)}
split_grep_test {split_grep(str)}
end

Résultats:

Running each test 262144 times. Test will take about 5 minutes.
split_start_with_test is similar to with_scan_test
with_scan_test is faster than with_gsub_test by 60.00000000000001% ± 1.0%
with_gsub_test is faster than split_grep_test by 30.000000000000004% ± 1.0%

1 pour la réponse № 4

Tu pourrais essayer ça

string.split(" ").select { |e| e.start_with?("#") }.join(" ")

Explication

split - Décompose une chaîne en un tableau de sous-chaînes basé sur un délimiteur, dans ce cas un espace

select - Utilisé pour filtrer un tableau qui correspond à l'expression transmise

|e| e.start_with?("#") - Trouver uniquement les sous-chaînes commençant par un signe dièse

join(" ") - Utilisé pour transformer un tableau en chaîne