在Ruby中将哈希扁平化为字符串

时间:2010-06-15 16:17:35

标签: ruby hash

有没有办法将哈希压缩成字符串,键和值之间有可选的分隔符,以及键/值对?

例如,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'

由于

6 个答案:

答案 0 :(得分:105)

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

  

返回一个新的数组   一维扁平化   哈希值。也就是说,对于每个键或值   这是一个数组,提取其元素   进入新阵列。不像   数组#flatten,此方法没有   默认情况下递归展平。如果   可选的level参数决定了   递归水平变平。

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

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

答案 1 :(得分:22)

@ 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'

答案 2 :(得分:5)

嗯,你可以用标准方法和数组来做到这一点:

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 ...

答案 3 :(得分:4)

如果您正在尝试生成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"

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:0)

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

有很多适用于ruby的JSON工具。但是从来没有试过它们。但是输出当然会更容易滑入javascript等。可能一行。

虽然在文档方面会有很大的节省,但是你需要更少的钱。