【问题标题】:Incrementation in Ruby hashesRuby 哈希的增量
【发布时间】:2014-05-21 00:53:06
【问题描述】:

我正在尝试增加哈希中的键。例如。我正在努力解决这个问题

{:b => "crayons", :c => "colors", :d => "apples"} 

变成这样

{:c => "crayons", :d => "colors", :e => "apples"} 

我认为这段代码可以解决问题,但事实并非如此。我需要改变什么?

def hash(correct)
  mapping = correct.each{|key, element| key.next}
  Hash[correct.map {|key, element| [mapping[key], element]}]
end

【问题讨论】:

  • 一般来说,使用变量等符号并以编程方式创建新符号并不是一个好主意。
  • 扩展 Mark 的评论,这是因为分配给 Symbol 对象的内存永远不会被垃圾回收。

标签: ruby hashmap


【解决方案1】:

使用Enumerable#each_with_object

def hash_correct(hsh)
  hsh.each_with_object({}) { |(k,v), hsh| hsh[k.succ] = v }
end

hash_correct({:b => "crayons", :c => "colors", :d => "apples"})
# => {:c=>"crayons", :d=>"colors", :e=>"apples"}

【讨论】:

    【解决方案2】:
    def hash(correct)
      Hash[correct.map{|key, element| [key.next, element]}]
    end
    

    【讨论】:

      【解决方案3】:
      h = {:b => "crayons", :c => "colors", :d => "apples"}
      
      h.keys.map(&:succ).zip(h.values).to_h
        #=> {:c=>"crayons", :d=>"colors", :e=>"apples"}
      

      如果意图是修改(而不是保留)原始哈希,则可以就地完成更新:

      keys = h.keys.reverse
      keys.each { |k| h[k.succ] = h[k] }
      h.delete(keys.last)
      

      可以理解为:

      h.delete(h.keys.reverse.each { |k| h[k.succ] = h[k] }.last)
      

      【讨论】:

        【解决方案4】:
        def hash(correct)
          exp_hash = correct.map { | k, v|  {k.next => v}  }
          Hash[*exp_hash.collect{|h| h.to_a}.flatten]
        end
        
        correct = {:b => "crayons", :c => "colors", :d => "apples"}
        

        【讨论】:

        • 如果你使用k.to_s,你不想要k.to_s.next.to_sym吗?就目前而言,这将返回 {"c"=>"crayons", "d"=>"colors", "e"=>"apples"}
        • 感谢@CarySwoveland。实际上在 ruby​​ 1.8.7 next 方法对于 Symbol class 不可用,这就是它首先转换为字符串的原因。无论如何,我现在已经为 ruby​​ 1.9.3 环境修改了这个答案。谢谢你让我知道:)
        • @cvibha 地球上的什么阻止您获取最新的 Ruby 版本。我不知道为什么很多人还在1.8.7。请升级。
        【解决方案5】:

        我认为这段代码可以解决问题,但事实并非如此。

        mapping = correct.each{|key, element| key.next}
        

        如果您访问 ruby​​ Symbol 文档并单击 next() 的链接...很惊讶没有 next() 条目,但窗口顶部的说明显示:

        成功
        与 sym.to_s.succ.intern 相同。

        由此你必须推断 next() 是 succ() 的同义词。所以 Symbol#next/succ 通过调用 to_s() 将符号转换为字符串。好吧,你知道你会得到一个从 to_s 返回的字符串,不管你对那个字符串做什么,例如在其上调用 String#succ,它不会影响某些符号,例如你的哈希键。此外,如果您查看 String#succ 的文档,它会说

        succ -> new_string

        ...所以 String#succ 创建另一个 String 对象并在该 String 对象上调用 intern(),顺便说一下,intern() 只是 to_sym() 的同义词,再次不会影响某些 Symbol.. .而且它甚至不会影响 to_s 返回的 String 对象。

        最后,intern() 不会改变第二个字符串对象,而是返回一个 Symbol:

                          a String
                            V
        key.next => key.to_s.succ.intern => Symbol
                                 ^
                               another String
        

        ...因为你没有对 intern() 返回的 Symbol 做任何事情,所以它被丢弃了。

        【讨论】:

          猜你喜欢
          • 2013-04-18
          • 2014-03-03
          • 2011-07-01
          • 1970-01-01
          • 2015-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-22
          相关资源
          最近更新 更多