2016-04-05 1 views
2

У меня есть массив Ruby (не спрашивайте меня, почему это не хэша уже, я ничего не могу поделать):Как разобрать однострочный массив на хэш в Ruby?

[{":cost=>100", ":size=>2"}] 

Что мне нужно сделать, чтобы это классический рубин хэш с ключами и значениями? Какой у меня лучший вариант? Может быть, есть несколько библиотек для такого рода операций?

Спасибо.

+5

Вы отправили недействительный код. Я думаю, что вы упустили (или вставили) '{}'. –

+0

Может быть, 'eval ('{' + [": cost => 100 ",": size => 2 "]. Join (',') + '}')'? – sschmeck

+0

Фактически нет. Это то, что я получаю с командой «puts», когда я пытаюсь проверять данные визуально. И я получаю класс «Array», когда я печатаю имя класса этого объекта с помощью puts (MyClass.class). –

ответ

1

Сначала нужно очистить строку, чтобы сделать его похожим на действительный массив:

my_string = my_string[2..-3] 
my_array = eval("[#{my_string}]") 

Теперь вы можете присоединиться строки, а затем Eval его в хэш:

elements = my_array.join(', ') 
my_hash = eval("{ #{ elements } }") 

(это можно сделать в меньшем количестве строк, но я отделил их для ясности)

+1

Стоит отметить, что всякий раз, когда вы используете 'eval', вы должны быть сверхчувствительным **, чтобы не выполнять произвольные строки. Будьте абсолютно уверены, что эти данные поступают из надежного источника. – tadman

1

Для этого вы можете использовать модуль JSON. Это было бы безопаснее, чем при использовании eval.

Чтобы посмотреть, как можно использовать JSON, давайте сделаем некоторые обратные разработки. Вы хотите создать хеш:

h = { :cost=>100, :size=>2 } 

из строки:

str = '[{":cost=>100", ":size=>2"}]' 
    #=> "[{\":cost=>100\", \":size=>2\"}]" 

Давайте посмотрим, как это хэш будет закодирован в виде строки JSON:

require 'json' 
jstr = JSON.generate(h) 
    #=> "{\"cost\":100,\"size\":2}" 

После того как мы jstr (который является не более чем строкой), мы можем извлечь желаемый хеш:

JSON.parse(jstr) 
    #=> {"cost"=>100, "size"=>2} 

поэтому задача сводится к преобразованию str в jstr:

"[{\":cost=>100\", \":size=>2\"}]" => "{\"cost\":100,\"size\":2}" 

Возможно, самый простой способ это первый вытащить ключи и значения, которые мы можем сделать с регулярным выражением:

r =/
    (  # start capture group 1 
     [a-z] # match a lowercase letter 
     \w* # match >= 0 word characters 
    )  # close capture group 1 
    =>  # match characters 
    (-?\d+) # optionally match a minus sign followed by > 0 digits in 
      # capture group 2 
    /x  # free-spacing regex definition mode 

arr = str.scan r 
    #=> [["cost", "100"], ["size", "2"]] 

Мы Теперь можно сформировать jstr:

jstr = "{#{ arr.map { |k,v| "\"#{k}\":#{v}" }.join(",") }}" 
    #=> "{\"cost\":100,\"size\":2}" 

Для подтверждения

h = JSON.parse(jstr) 
    #=> {"cost"=>100, "size"=>2} 
Смежные вопросы