举个例子,有若干个字符串(约 10w 行数据)
string = "Ruby China is a community of Ruby developers."
keywords = ["Ruby", "community"]
如何判断这个 string 中包括这个数组中的任何一个元素呢?
想到的一个很丑的写法是这样的:
if string.include? keywords[0] or string.include? keywords[1]
# do something
end
keywords 数组是变化的并且最多会有 100+,因此这种写法不可能成立的...
然后改了一下成这样:
keywords.each { | keyword | result.push(string) if string.include? keyword }
但是这样会造成如果这一句话包括多个关键字的话,会出现很多次。
所以想请教一下,有没有什么方法能够判断这个字符串是否包括数组中存在的这些子串,或者有更好地判断方法?
谢谢!
a = ["1", "2", "3"]
b = "1 2 3 4 5"
c = ["6"]
p "hello" if !(a & b.split(//)).empty?
p "haha" if !(c & b.split(//)).empty?
一个简单的写法。求交集。
string = "Ruby China is a community of Ruby developers."
# 加长string长度, 增加游戏难度
string_1000 = string * 1000
# 随机生成100个不定长串
keywords = 100.times.collect { SecureRandom.hex(rand(5) + 1) }
# 预先拼接好正则式
reg = Regexp.union(keywords)
# 匹配整词
reg_fullword = Regexp.new("\\b#{Regexp.escape(keywords.join('|'))}\\b")
n = 1_000
Benchmark.bm do |x|
puts 'string'
# 使用select
x.report { n.times { keywords.select { |keyword| string.include?(keyword) } } }
# 使用index
x.report { n.times { string.index(reg).nil? } }
# 使用index匹配整词
x.report { n.times { string.index(reg_fullword).nil? } }
# 使用any
x.report { n.times { keywords.any? { |k| string.include?(k) } } }
puts
puts 'string_1000'
x.report { n.times { keywords.select { |keyword| string_1000.include?(keyword) } } }
x.report { n.times { string_1000.index(reg).nil? } }
x.report { n.times { string_1000.index(reg_fullword).nil? } }
x.report { n.times { keywords.any? { |k| string_1000.include?(k) } } }
end
user system total real
string
0.030000 0.000000 0.030000 ( 0.027699)
0.000000 0.000000 0.000000 ( 0.001021)
0.000000 0.000000 0.000000 ( 0.000865)
0.020000 0.000000 0.020000 ( 0.025702)
string_1000
2.170000 0.010000 2.180000 ( 2.175521)
0.000000 0.000000 0.000000 ( 0.001211)
0.020000 0.000000 0.020000 ( 0.012870)
2.130000 0.000000 2.130000 ( 2.136878)
第一反应是用正则,贴出 (没有测试性能):
string = "Ruby China is a community of Ruby developers."
keywords = ["Ruby", "community"]
reg = Regexp.new keywords.join("|");
# if want to test true or false
if string =~ reg
# do something
end
# if want to get all matched string
p string.scan(reg)
# => ["Ruby", "community", "Ruby"]
希望有帮助吧
个人觉得用 string.include? t
这样的写法是 ruby 的专有福利,属于黑魔法。
正则则是通用的玩法,所有的语言都支持,都可以这样玩,这样折腾。
我一个同事给我的影响很大,他擅长用一切语言写应用。哪怕这语言重来都没摸过,他都开着 google 用它写应用。因为他的能力与语言无关。
#13 楼 @suffering 我想了一个方法,能麻烦帮忙看下有没有什么问题吗?
keywords.each do |keyword|
if line.include? keyword
# do_something
break
end
end