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 № 1Je 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