Сглаживание хеша в строку в Ruby - PullRequest
48 голосов
/ 15 июня 2010

Есть ли способ скомбинировать хеш в строку с необязательными разделителями между ключами и значениями и парами ключ / значение?

Например, 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 ]

105 голосов
/ 15 июня 2010

Я бы не переопределил .flatten, который уже определен:

Возвращает новый массив, который является одномерное уплощение этого хэш. То есть для каждого ключа или значения это массив, извлеките его элементы в новый массив. В отличие от Array # flatten, этот метод не по умолчанию рекурсивно. Если необязательный аргумент уровня определяет уровень рекурсии для выравнивания.

Это самый простой способ сделать это, о котором я знаю:

{:a => 100, :b => 200}.map{|k,v| "#{k}=#{v}"}.join('&')
# => "a=100&b=200"
22 голосов
/ 15 июня 2010

Небольшое изменение версии @ 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 голосов
/ 15 июня 2010

Ну, вы можете сделать это стандартными методами и массивами:

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

Вас также может заинтересовать метод Rails to_query .

Также, очевидно, вы можете написать "#{k}#{keyvaldelimiter}#{v}" как k.to_s + keyvaldelimiter + v.to_s ...

4 голосов
/ 20 марта 2012

Если вы пытаетесь сгенерировать строку запроса URL, вам, безусловно, следует использовать метод, подобный to_param activesupport (с псевдонимом 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"

Важно избежать, иначе операция необратима.

1 голос
/ 15 июня 2010

Не уверен, есть ли встроенный способ, но вот более короткий код:

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
0 голосов
/ 16 июня 2010

Как насчет получения его в формате JSON.Таким образом, формат понятен.

Существует множество инструментов JSON для ruby.Никогда не пробовал их, хотя.Но результат, конечно же, будет легче вставлять в javascript и т. Д.Скорее всего одна строка.

Большая экономия, хотя бы в документации, в том, что вам потребуется гораздо меньше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...