2009-09-28 42 views
7

这似乎是一个可笑的简单问题,但是在Ruby中重写这个最短/最常用的方式是什么?确定变量是否是值列表中的任何一个的最短/最常用的方式是什么?

if variable == :a or variable == :b or variable == :c or variable == :d # etc. 

我看到这个解决方案:

if [:a, :b, :c, :d].include? variable 

,但是这并不总是功能相当的 - 我相信Array#include?实际上看起来,看看是否变量对象被包含在列表中;它没有考虑到对象可以用def ==(other)执行它自己的平等测试。

正如下面有用的评论员所观察到的那样,这种解释是不正确的。 include?确实使用==,但它使用数组中项目的==方法。在我的例子中,它是符号,而不是变量的==方法。这就解释了为什么它不等同于我的第一个代码示例。

(举个例子来说,Rails的Mime::Type实现:request.format == :html可能返回true,但[:html].include?(request.format)将返回false,因为request.format是哑剧::类型,而不是一个符号实例。)

我有最好的到目前为止是:

if [:a, :b, :c, :d].select {|f| variable == f}.any? 

但似乎有点麻烦我。有没有人有更好的建议?

+0

我认为,“任何”语法看起来很干净。但是,我是C#,而且很像镜像LINQ的外观,所以我很偏向。 – 2009-09-28 13:40:10

+0

文件说明:Array#include?如果给定对象存在于self中(即,如果有任何对象== anObject),则返回true,否则返回false。 – khelll 2009-09-28 13:58:52

+0

我不知道在Object类中实现isOneOf?(array)方法在ruby中不被认为是一种好的做法,我的意思是,与基类混淆(显然,我没有使用ruby的经验)......无论如何,它会如果有人可以发布这样的方法,请罚款...... – opensas 2009-10-01 01:50:51

回答

15

实际上,#include?确实使用==。这个问题源于,如果你做

[:a].include? foo 

它检查:a == foo,不foo == :a的事实。也就是说,它使用在数组中的对象上定义的==方法,而不是变量。因此,只要确保阵列中的对象具有适当的==方法,就可以使用它。

在情况下,这是行不通的,你可以通过删除select语句,并直接传递块any简化您的语句:

if [:a, :b, :c, :d].any? {|f| variable == f} 
+0

啊哈!我想你已经钉住了我的#include?问题 - 谢谢,这很有道理。 回到手边的问题,我也喜欢你将方块传递给任何方法吗? - 对我来说看起来很干净。 – NeilS 2009-09-28 14:17:26

1

我一直使用你的第二个例子,if [:a, :b, :c, :d].include? variable。虽然这确实带来了一些覆盖==的类的问题,但在大多数情况下我都需要它(通常检查符号),这是完全正确的。

+0

感谢您的意见。今天我被[:html,:xml] .include?(request.format)咬了,总是在Rails应用程序中返回false,所以我想我可能需要让自己摆脱这种习惯! – NeilS 2009-09-28 13:53:26

+2

也许你可以写'[:html,:xml] .include?(request.format.to_sym)' – 2009-09-28 14:56:19

1

如何:

if [:a, :b, :c, :d].index variable 
+0

感谢您的评论,非常感谢。尽管如此,我认为展现出与#include相同的行为 - 大概是出于Pesto在他的评论中解释的相同原因。 – NeilS 2009-09-28 14:25:49

0

你真正做的是看是否变量是集[:a,:b,:c,:d]的成员,因此语义映射到include?方法。

你遇到的问题是由于红宝石的鸭打字性质,所以如果你想避开那为什么不首先转换为符号:

if [:a, :b, :c, :d].include? variable.to_sym 
+0

感谢您的评论,很感谢。这在很多情况下都有效,但如果所讨论的对象在其平等的定义中实现了更多的逻辑,那么这当然不起作用。 (例如,也许它也会与同义词列表进行比较。) – NeilS 2009-09-28 14:13:13

3

它看起来像Array#include?确实使用==

>> class AString < String 
>> def ==(other) 
>>  self[0] == other[0] 
>> end 
>> end 

>> asdf = AString.new "asdfg" 
=> "asdfg" 
>> b = AString.new 'aer' 
=> "aer" 

>> asdf == b 
=> true 

>> [asdf].include? b 
=> true 

Array#include?文档也解释了这一点。

+0

感谢您的分析;非常感谢。我被上面观察到的Pesto观察到的问题所迷惑,因此我感到困惑。 – NeilS 2009-09-28 14:09:27

相关问题