Сжатие хэша в строку в 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'
Спасибо
Ответы
Ответ 1
Я бы не переопределял .flatten
, который уже определен:
Возвращает новый массив, который является одномерное сглаживание этого хэш. То есть для каждого ключа или значения это массив, извлекать его элементы в новый массив. В отличие от Array # flatten, этот метод не по умолчанию рекурсивно выравнивается. Если необязательный аргумент уровня определяет уровень рекурсии к сплющиванию.
Это самый простой способ сделать это, о котором я знаю:
{:a => 100, :b => 200}.map{|k,v| "#{k}=#{v}"}.join('&')
# => "a=100&b=200"
Ответ 2
Небольшое изменение версии @elektronaut:
Вместо |k, v|
вместо |k, v|
можно разместить только |e|
, и в этом случае 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'
Ответ 3
Ну, вы можете сделать это со стандартными методами и массивами:
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
...
Ответ 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"
Важно выйти, иначе операция не будет обратимой.
Ответ 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. Таким образом, формат понятен.
Есть много инструментов JSON для рубинов. Тем не менее, они никогда не пробовали. Но тогда результат, конечно, будет скользить в javascript и т.д. Вероятно одна строка.
Большая экономия, хотя и будет в документации, в том, что вам понадобится гораздо меньше.