#map_find 在 Ruby 中?
Posted
技术标签:
【中文标题】#map_find 在 Ruby 中?【英文标题】:#map_find in Ruby? 【发布时间】:2020-01-16 21:58:32 【问题描述】:返回一组文本行中匹配的第一个关键字。
我发现#map
和#find
和#find
再次解决了问题。一个不令人满意的复杂解决方案。
["unrelated", "start something", "stop something"].map do |t|
["start","stop"].find |k| k == t.split(/[ \t]1,/).first
end.find |k| !k.nil?
上述返回"start"
符合预期。 #map_find
这样的便捷方法可以压缩它。或者可能已经存在针对这个问题的聪明的选择算法。请指教。
编辑
另一种解决方案:
keys = ["start", "stop"]
reg = Regexp.new("^"+keys.first+" |^"+keys.last+" ")
["unrelated", "start something", "stop something"].map|m| m.slice(reg).find |k| !k.nil?
【问题讨论】:
从您的示例中有点不清楚哪个顺序更重要 - 行中的顺序或关键字。如果关键字是%w[stop start]
或行是['stop something', 'start something']
,那么在这种情况下,您是否仍然期望返回start
或期望stop
?
在你的例子中,我希望stop
。匹配关键字的第一行定义了返回的关键字。
这也可以:keyword = arr.find |a| a[/\A(start|stop)\b/] && Regexp.last_match[0]
(或更短:arr.find |a| a[/\A(start|stop)\b/] && $1
)
您的实现仍然比我的快 4 倍。到现在已经节省了十分之二秒 :)
【参考方案1】:
我会这样做:
lines = ["unrelated", "start something", "stop something"]
keywords = /\A(start|stop)/
lines.lazy.map |line| line[keywords] .find(&:itself)
#=> "start"
当lines
的数量很少时,您可能希望跳过lazy
。它越大,您从lazy
中受益越多。
【讨论】:
我需要返回匹配的关键字,而不是行。 出于某种原因,您的原始解决方案比我的任何一个都快 11 倍。 因为lazy
——这增加了一些初始开销——我的版本将map
直到找到匹配的行然后立即返回。您的版本将在检查条件之前首先评估所有行 - 即使匹配已经在第二个元素上(如您的示例中)。
lazy
增加了一致的惩罚,速度基本和我的一样。如果没有最新版本,速度会快 4 倍。
正如我在回答中已经写的那样。如果行数很大,请仅使用lazy
。数量少的话不值得。以上是关于#map_find 在 Ruby 中?的主要内容,如果未能解决你的问题,请参考以下文章