使哈希键映射到相同的值

时间:2015-09-28 21:41:05

标签: ruby hash key mapping

这是我的哈希:

color_hash = { sky: "blue", curtain: "blue", pavement: "black" }

有没有办法改变它以使两个键映射到相同的结果,如下所示:

color_hash = { sky or curtain: "blue", pavement: "black" }

我希望能够使用color_hash[:sky]并打印blue,我可以使用color_hash[:curtain]并打印blue

3 个答案:

答案 0 :(得分:1)

不,没有办法在Ruby中使用默认的哈希实现。见Is Ruby pass by reference or by value?。如果这是可能的,那么Hash上的setter方法[]=必须以允许您通过引用传递的方式实现。

你可以使用一些kludgy语法和Hash的子类实现类似的东西......这样的事情(只是一个警告,这仍然是错误的并且相当未经测试,但是让你知道可能涉及的内容)

class FooHash < Hash
  attr_accessor :related

  def initialize(*args)
    @related = {}
    super
  end

  def []=(*args)
    raise ArgumentError.new("ArgumentError: wrong number of arguments (#{args.length} for 2)") unless args.length > 1
    value = args.pop
    keys = args.dup

    args.each_index do |index|
      key = keys.delete_at(index)
      if related[key]
        related[key].each do |related_key|
          continue if keys.include?(related_key)
          super(related_key, value)
        end
      else 
        related[key] = []
      end
      related[key] += keys
      related[key].uniq!
      keys.insert(index, key)
    end

    args.each do |arg|
      super(arg, value)
    end
  end
end

它可以让你做这样的事情:

1.9.3-p550 :036 > hsh = FooHash.new
 => {}
1.9.3-p550 :037 > hsh[:foo, :bar] = :baz
 => :baz
1.9.3-p550 :038 > hsh[:foo]
 => :baz
1.9.3-p550 :039 > hsh[:bar]
 => :baz
1.9.3-p550 :040 > hsh[:foo, :blah] = "baz2"
 => "baz2"
1.9.3-p550 :041 > hsh[:foo]
 => "baz2"
1.9.3-p550 :042 > hsh[:bar]
 => "baz2"
1.9.3-p550 :043 > hsh[:blah]
 => "baz2"

长话短说但是,试图模仿Ruby中的指针操作有点粗暴,不要这样做。

答案 1 :(得分:1)

即使我理解你想要做什么,也要考虑使用不同的数据结构。

color_hash = { sky: "blue", pothole: "black", curtain: "blue",
               pavement: "black", roadblock: "red" }

您可以使用Enumerable#group_by

color_hash.group_by(&:last).tap { |h| h.each_key { |k| h[k].map!(&:first) } }
  #=> {"blue"=>[:sky, :curtain], "black"=>[:pothole, :pavement],
  #    "red"=>[:roadblock]} 

Hash#update

color_hash.each_with_object({}) { |(k,v),h|
  h.update(v=>[k]) { |_,o,n| o+n } }
  #=> {"blue"=>[:sky, :curtain], "black"=>[:pothole, :pavement],
  #    "red"=>[:roadblock]}

这使用Hash#update(又名merge!)的形式,它使用一个块来确定合并的两个哈希中存在的键的值。这里{ |_,o,n| o+n }就是那个块,其中(局部变量)_是关键(而不是k,告诉读者它没有在计算中使用),{ {1}}(“old”)是该键的哈希o的值,h是该键合并的哈希值。

答案 2 :(得分:0)

或许试试这个。

  $someHashContainer = {:curtain => "Blue", :sky => "Blue"}

  def update_variables(value)
    $someHashContainer[:curtain] = value
    $someHashContainer[:sky] = $someHashContainer[:curtain]
  end

  puts $someHashContainer

  update_variables("Green")
  puts $someHashContainer

  $someHashContainer[:curtain] = "Red"
  puts $someHashContainer

  update_variables("Yellow")
  puts $someHashContainer


'''
OUTPUT:
{:curtain=>"Blue", :sky=>"Blue"}
{:curtain=>"Green", :sky=>"Green"}
{:curtain=>"Red", :sky=>"Green"}
{:curtain=>"Yellow", :sky=>"Yellow"}
'''