从文本中提取(并修改)以特定字符串开头的所有单词?

时间:2014-02-20 19:44:38

标签: ruby regex arrays

我正在寻找一种更有效的方法来从以特定字符串开头的文本块中选择单词。如果可能的话,我也想同时修改它们。在我的情况下,我希望找到主题标签并将其缩写,因此给出一个字符串:

the quick brown #Fox jumps over the lazy #dog

我想制作数组:

["#fox","#dog"]

甚至:

["fox","dog"]

目前我的(可能是效率低下的)代码看起来像这样:

words = item.body.split(" ")
tagged_words = words.select{|x| x[0,1] == "#"}
tagged_words = tagged_words.map{ |x| x.downcase }

我假设前两行可以用正则表达式替换,但无法弄清楚。也许甚至有一种方法可以将所有三行代码组合在一起?

这一部分可能与群众关系不大,但我最终想要做的是获取完整的标签列表并将其减少为仅在项目主体内未引用的标签。这需要一行代码,所以要感谢任何可以重写整个过程的人,以获得更高的效率。

external_tags = item.tags.select{|tag| !tagged_words.include?("#"+tag.name)}

我搜索了一段时间以回答我问题的第一部分,但找不到答案。任何回复/评论引用我对更一般性问题的答案肯定就足够了。

5 个答案:

答案 0 :(得分:2)

s = "the quick brown #Fox jumps over the lazy #dog"
p s.scan(/(^|\s)#(\S+)/).map { |m| m[1].downcase }
# => ["fox", "dog"]

如果我错了,请纠正我,但是一旦这部分工作,你似乎已经回答了问题的第二部分。

答案 1 :(得分:1)

只抓住标签:

'the quick brown #Fox jumps over the lazy #dog'.scan(/#\S+/)
# => ["#Fox", "#dog"]

如果您不想要哈希标记:

'the quick brown #Fox jumps over the lazy #dog'.scan(/(?<=#)\S+/)
# => ["Fox", "dog"]

使用后视匹配但不捕获“#”字符。

或者:

'the quick brown #Fox jumps over the lazy #dog'.scan(/#\S+/).map{ |s| s.tr('#', '') }
# => ["Fox", "dog"]

或者:

'the quick brown #Fox jumps over the lazy #dog'.scan(/#\S+/).map{ |s| s.delete('#') }
# => ["Fox", "dog"]

或者:

'the quick brown #Fox jumps over the lazy #dog'.scan(/#\S+/).map{ |s| s.sub('#', '') }
# => ["Fox", "dog"]

答案 2 :(得分:0)

tag_string = "the quick brown #Fox jumps over the lazy #dog"
tag_string.split(" ").select{|a| /^#/.match(a)}.map(&:downcase)

答案 3 :(得分:0)

这个怎么样? (Positive lookbehind

str = "the quick brown #Fox jumps over the lazy #dog"
str.scan(/#\w+/)
=> ["#Fox", "#dog"]

# using Positive lookbehind 
str.scan(/(?<=#)\w+/)
=> ["Fox", "dog"]

str.scan(/(?<=#)\w+/).map(&:downcase)
=> ["fox", "dog"]

答案 4 :(得分:0)

关于单词字符和单词边界的全部内容:

"the quick brown #Fox jumps over the lazy #dog".scan /\B#\w+\b/
#=> ["#Fox", "#dog"]

帮自己一个忙,learn all about them