0

我必须在数组中搜索一个项目并返回下一个项目的值。例子:

a = ['abc.df','-f','test.h']
i = a.find_index{|x| x=~/-f/}
puts a[i+1]

除了使用索引之外,还有什么更好的方法吗?

4

4 回答 4

3

经典的函数方法不使用索引(xs.each_cons(2)-> xs 的成对组合):

xs = ['abc.df', '-f', 'test.h']
(xs.each_cons(2).detect { |x, y| x =~ /-f/ } || []).last
#=> "test.h"

使用Enumerable#map_detect可以稍微简化一点:

xs.each_cons(2).map_detect { |x, y| y if x =~ /-f/ }
#=> "test.h"
于 2012-07-02T20:53:11.443 回答
3

类似的东西array.find{something}.next不存在的原因是它是一个数组而不是链表。每一件物品都是它自己的价值;它没有“我之后的项目”的概念。

@tokland 通过使用每对连续项目迭代数组提供了一个很好的解决方案,这样当第一个项目匹配时,您就可以方便地使用第二个项目。可以肯定的是,对于函数式风格有很强的论据。不过,您的版本更短,而且我认为您的版本也更快速、更容易理解。

如果问题是您经常使用它并且想要一些更清洁和更重要的东西,那么您当然可以将它作为单例方法添加到a

def a.find_after(&test)
  self[find_index(&test).next]
end

然后

a.find_after{|x| x=~/-f/}

是在第一次匹配后找到下一个项目的清晰方法。

综上所述,我认为@BenjaminCox 对您的实际目标提出了最佳观点。如果您正在解析命令行选项,那么有些库可以做得很好。

于 2012-07-02T22:44:48.010 回答
1

我不知道执行该特定操作的更清洁方法。但是,看起来您确实在尝试解析命令行参数。如果是这样,我建议使用内置的 OptionParser 模块 - 它会节省大量时间和头发拉扯试图自己解析它们。

这篇文章解释了它是如何工作的。

于 2012-07-02T20:49:46.337 回答
0

正如其他人所评论的那样,您使用索引的解决方案很好。您可以使用Enumerable#drop_while从匹配中获取数组并获取其中的第二个元素:

a = ['abc.df','-f','test.h']
f_arg = a.drop_while { |e| e !~ /-f/ }[1]
于 2012-07-02T22:49:07.403 回答