2010-06-15 46 views
40

有没有一种方法可以将哈希平化为字符串,在键和值之间使用可选的分隔符以及键/值对?将哈希平铺到Ruby中的字符串

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

感谢

回答

92

我不会重写.flatten ,这是已经被定义:

返回一个新数组,它是此的 一维展平散列。也就是说,对于作为数组的每个键或值 ,将其元素 提取到新数组中。与 数组#平展不同,默认情况下,此方法不会 递归平展。如果 可选级别参数确定要递减的 递归级别。

这是为了做到这一点,我所知道的最简单的方法:

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

您可以进一步简化此操作。详情请参阅我的回答。要点是用'| e |'代替'| k,v |',这使'e'成为一个可以调用'e.join('=')'的数组。 – 2010-06-15 18:33:06

+1

如何做相反得到散列 – jenuine 2016-02-19 06:12:58

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

+2

或'[k,v] .join(keyvaldelimiter)'。 – henrikhodne 2010-06-15 16:32:01

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 
21

的@ 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' 
+5

我会严重质疑它是如何聪明是猴子补丁'哈希',特别是与一个非命名空间的方法名称,如'加入'。虽然我期望得到这个,但我很惊讶地看到一位非常有经验的开发人员的这种建议。 – akostadinov 2016-03-25 14:32:00

0

怎么样得到它在JSON格式。这样的格式很清楚。

有很多用于ruby的JSON工具。虽然从未尝试过。但是输出当然会更容易滑入javascript等。可能只有一行。

尽管会在文档中节省大笔费用,因为您将需要更少的费用。

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" 

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

+0

这一切都很好,这是一个很好的观点,但我宁愿不要求在创建源代码散列时安装Rails – 2012-03-24 17:36:46

+0

Rails for win! – 2016-07-13 20:18:05