Spłaszczanie hasha na string w Ruby
Czy istnieje sposób na spłaszczenie hasha w łańcuch z opcjonalnymi ogranicznikami między kluczami i wartościami oraz parami klucz/wartość?
Na przykład, print {:a => :b, :c => :d}.flatten('=','&')
powinien wydrukować a=b&c=d
Napisałem jakiś kod, aby to zrobić, ale zastanawiałem się, czy nie ma lepszego sposobu:
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'
Dzięki
6 answers
Nie nadpisałbym .flatten
, który jest już zdefiniowany:
Zwraca nową tablicę, która jest jednowymiarowe spłaszczenie tego hash. Oznacza to, że dla każdego klucza lub wartości to jest tablica, wyodrębnij jej elementy do nowej tablicy. W przeciwieństwie do Array#flatten, ta metoda nie domyślnie spłaszcz rekurencyjnie. Jeśli opcjonalny argument poziomu określa poziom rekurencji do spłaszczenia.
Jest to najprostszy sposób, który znam:
{:a => 100, :b => 200}.map{|k,v| "#{k}=#{v}"}.join('&')
# => "a=100&b=200"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 16:33:01
Mała zmiana wersji @elektronauta:
Możesz umieścić tam tylko |e|
zamiast |k, v|
w takim przypadku e
jest tablicą dwóch elementów i możesz wywołać e.join('=')
. W sumie masz coś w stylu
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'
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 18:31:00
Cóż, można to zrobić standardowymi metodami i tablicami:
class Hash
def flatten(keyvaldelimiter, entrydelimiter)
self.map { |k, v| "#{k}#{keyvaldelimiter}#{v}" }.join(entrydelimiter)
end
end
Być może zainteresuje cię również metoda Rails to_query
.
Również, oczywiście, można zapisać "#{k}#{keyvaldelimiter}#{v}"
jako k.to_s + keyvaldelimiter + v.to_s
...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 16:27:17
Jeśli próbujesz wygenerować ciąg zapytania url, z pewnością powinieneś użyć metody takiej jak to_param activesupport (aliased to to_query). Wyobraź sobie problemy, jeśli masz Znak ampersand lub equal w samych danych.
To_query dba o ucieczkę:
>> require 'active_support/core_ext/object'
>> {'a&' => 'b', 'c' => 'd'}.to_query
>> => "a%26=b&c=d"
EDIT
@fahadsadah ma rację, że nie chce ładować szyn. Nawet active_support / core_ext / object załaduje 71 plików. Posiada również podstawowe klasy.
Lekki i roztwór czyszczący:
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"
To ważne, aby uciec, inaczej operacja nie jest odwracalna.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-24 22:58:21
Nie wiem, czy jest wbudowany sposób, ale tu jest jakiś krótszy kod:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 16:27:33
A co z zapisaniem go w formacie JSON? W ten sposób format jest jasny.
Istnieje wiele narzędzi JSON dla Rubiego. Nigdy ich nie próbowałem. Ale wyjście będzie oczywiście przesuwać do javascript, itp łatwiejsze. Prawdopodobnie jedna linijka.
Duże oszczędności, choć byłoby w dokumentacji, w tym trzeba znacznie mniej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-15 20:24:07