【问题标题】:Flattening hash into string in Ruby在Ruby中将哈希展平为字符串
【发布时间】:2011-03-04 02:02:24
【问题描述】:

有没有办法将散列扁平化为字符串,在键和值之间以及键/值对之间使用可选的分隔符?

例如,print {:a => :b, :c => :d}.flatten('=','&') 应该打印 a=b&c=d

我为此编写了一些代码,但我想知道是否有更简洁的方法:

class Hash
  def flatten(keyvaldelimiter, entrydelimiter)
    string = ""
    self.each do
      |key, value|
      key = "#{entrydelimiter}#{key}" if string != "" #nasty hack
      string += "#{key}#{keyvaldelimiter}#{value}"  
    end
    return string
  end
end

print {:a => :b, :c => :d}.flatten('=','&') #=> 'c=d&a=b'

谢谢

【问题讨论】:

    标签: ruby hash


    【解决方案1】:

    我不会覆盖已经定义的.flatten

    返回一个新数组,它是 这个的一维展平 哈希。也就是说,对于每个键或值 那是一个数组,提取它的元素 进入新数组。不像 Array#flatten,这个方法没有 默认情况下递归展平。如果 可选级别参数确定 要展平的递归级别。

    据我所知,这是最简单的方法:

    {:a => 100, :b => 200}.map{|k,v| "#{k}=#{v}"}.join('&')
    # => "a=100&b=200"

    【讨论】:

    • 你可以进一步简化这个。有关详细信息,请参阅我的答案。要点是将|k, v| 替换为|e|,这使得e 成为一个可以调用e.join('=') 的数组。
    • 如何反向获取哈希
    • 我更喜欢{ a: 100, b: 200 }.map {|h| h.join '=' }.join '&'。稍微干净一点。
    【解决方案2】:

    @elektronaut 的版本略有不同:

    您实际上可以只放一个|e| 而不是|k, v|,在这种情况下e 是一个包含两个元素的数组,您可以调用e.join('=')。总而言之,你有类似的东西

    class Hash
      def join(keyvaldelim=$,, entrydelim=$,) # $, is the global default delimiter
        map {|e| e.join(keyvaldelim) }.join(entrydelim)
      end
    end
    
    {a: 100, b: 200}.join('=', '&') # I love showing off the new Ruby 1.9 Hash syntax
    # => 'a=100&b=200'
    

    【讨论】:

    • 我会严重质疑猴子补丁Hash 的聪明程度,尤其是使用像join 这样的非命名空间方法名称。虽然我对很多人都抱有这样的期望,但看到一位经验丰富的开发人员提出这样的建议,我感到非常惊讶。
    【解决方案3】:

    如果你想生成一个 url 查询字符串,你当然应该使用像 activesupport 的 to_param(别名为 to_query)这样的方法。想象一下,如果数据本身有一个 & 或等号会出现什么问题。

    to_query 负责转义:

    >> require 'active_support/core_ext/object'
    >> {'a&' => 'b', 'c' => 'd'}.to_query
    >> => "a%26=b&c=d"
    

    编辑

    @fahadsadah 对不想加载 Rails 提出了一个很好的观点。即使是 active_support/core_ext/object 也会加载 71 个文件。它还猴子补丁核心类。

    轻量级和更清洁的解决方案:

    require 'rack'  # only loads 3 files
    {'a&' => 'b', 'c' => 'd'}.map{|pair|
      pair.map{|e| Rack::Utils.escape(e.to_s) }.join('=')
    }.join('&')
    # => "a%26=b&c=d"
    

    逃跑很重要,否则操作是不可逆的。

    【讨论】:

    • 这一切都很好,这是一个好点,但我宁愿在创建源哈希时不需要安装 Rails
    • 为胜利而战!!
    【解决方案4】:

    好吧,您可以使用标准方法和数组来做到这一点:

    class Hash
      def flatten(keyvaldelimiter, entrydelimiter)
        self.map { |k, v| "#{k}#{keyvaldelimiter}#{v}" }.join(entrydelimiter)
      end
    end
    

    您可能还对Rails to_query method 感兴趣。

    另外,很明显,你可以把"#{k}#{keyvaldelimiter}#{v}"写成k.to_s + keyvaldelimiter + v.to_s...

    【讨论】:

    • [k,v].join(keyvaldelimiter)
    【解决方案5】:

    不确定是否有内置方式,但这里有一些更短的代码:

    class Hash
      def flatten(kvdelim='', entrydelim='')
        self.inject([]) { |a, b| a << b.join(kvdelim) }.join(entrydelim)
      end
    end
    
    puts ({ :a => :b, :c => :d }).flatten('=', '&') # => a=b&c=d
    

    【讨论】:

      【解决方案6】:

      如何以 JSON 格式获取它。这样格式就清楚了。

      Ruby 有很多 JSON 工具。不过,从未尝试过。但是输出当然会滑入javascript等更容易。可能是一行。

      虽然可以节省大量文档,但您需要的更少。

      【讨论】:

        猜你喜欢
        • 2010-11-05
        • 2013-07-06
        • 2014-09-24
        • 1970-01-01
        • 2015-04-02
        • 1970-01-01
        • 2013-05-06
        • 1970-01-01
        • 2012-03-31
        相关资源
        最近更新 更多