Ruby 测试集合索引类型(即[]方法的参数)

Ruby 测试集合索引类型(即[]方法的参数),ruby,Ruby,如果一个集合支持字符串索引,那么什么是一种高效的rubyesque测试方法 长版本: 我想让我的一个类规范化某些值。为了实现这一点,实例将值的集合作为其“values”属性。我希望values=同时接受列表(整数索引集合,包括内置数组)和关联数组(对象索引集合,如散列)。如果传递了列表,它将通过反转键和值将列表转换为关联数组。这意味着该方法需要区分列表和关联数组。它还应该适用于任何索引集合,而不仅仅是数组和散列的后代,因此任何嗅探集合类型的类型都被认为是丑陋和错误的。类型嗅探索引类型,但是 目前

如果一个集合支持字符串索引,那么什么是一种高效的rubyesque测试方法

长版本: 我想让我的一个类规范化某些值。为了实现这一点,实例将值的集合作为其“values”属性。我希望
values=
同时接受列表(整数索引集合,包括内置数组)和关联数组(对象索引集合,如散列)。如果传递了列表,它将通过反转键和值将列表转换为关联数组。这意味着该方法需要区分列表和关联数组。它还应该适用于任何索引集合,而不仅仅是数组和散列的后代,因此任何嗅探集合类型的类型都被认为是丑陋和错误的。类型嗅探索引类型,但是

目前,我正在使用异常来区分差异,但我更喜欢在异常情况下使用异常,而不是一般的控制结构。这只是个人喜好,我不太喜欢。如果异常是解决此问题的ruby方法,请让我知道

def values=(values)
    begin
        values['']
        @values = values.dup
    rescue TypeError
        @values = Hash[ values.zip((0..values.length-1).to_a) ]
    end
    @values.each_value { |v| @values[v] = v}
end
注意:一个完整的解决方案将采用
的传递闭包,但现在我可以假设
的键和值来自不同的域

所有这些的要点是启用以下代码:

toggle.values = [:off, :on]
toggle.normalise(:off) == 0
toggle.normalise(1) == 1

bool.values = {:off => 0, :false => 0, :no => 0,
               :on => 1,  :true => 1,  :yes => 1}
bool.normalise(:yes) == 1
bool.normalise(0) == 0

这是一个个人项目,所以优雅和红宝石风格是最重要的。我正在寻找有趣的方法,特别是如果它们说明了一个有趣的概念(例如“异常可以用作行为测试”)。

鸭子键入来拯救

 hash = if collection.respond_to? :to_hash
          collection.to_hash
        elsif collection.respond_to? :to_ary
          collection.to_ary.inject({}) { |_hash,(key,value)| _hash.merge!(key => value) }
        else if collection.respond_to? :inject
          collection.inject({}) { |_hash,(key,value)| _hash.merge!(key => value) }
        else
          raise ArgumentError, "not a collection type I understand"
        end
 if want_dupe and collection.object_id == hash.object_id
    hash = hash.dup
 end

耶,鸭子打字!有没有任何干净的方法可以确保collection.to_hash是一个副本,而不创建中间的临时副本(就像collection.to_hash.dup可能做的那样)?“看,天空!它是一只鸟。它是一个平面。不,我第一次是对的,它是一只鸟。”你可以比较对象ID。这不像神奇的清洁,但它很有效。