2013-11-13 4 views
3

У меня есть хэш, который имеет неизвестную коллекцию и смесь вложенных массивов, хэшей, массивов хешей и строк. Это результат JSON.parse. Структура данных должна быть такой же, как и в начале. Конечной целью является преобразование строк в Fixnums, которые могут быть Fixnums.Ruby рекурсивная карта хэша объектов

Следующие работы прекрасно, но мне было интересно, можно ли сократить его. Обратите внимание, как мне нужен ключ и значение в методе clean, поскольку не все строки, которые могут быть Fixnums, должны быть. Есть идеи?

def clean_node(node) 
    if node.class == String 
     clean(node) 
    elsif node.class == Array 
     node.each_with_index do |obj, i| 
     if obj.class == String 
      node[i] = clean(node[i], obj) 
     else 
      clean_node(obj) 
     end 
     end 
    elsif node.class == Hash 
     node.each_pair do |key, value| 
     if value.class == String 
      node[key] = clean(key, value) 
     else 
      clean_node(value) 
     end 
     end 
    end 
end 

def clean(key, value) 
    FIXNUM_KEYS.include?(key)? value.to_i : value 
end 
+3

Вы сами генерируете JSON? Похоже, что JSON содержит числа как строки. Я бы скорее попытался исправить код, который генерирует JSON. –

+0

В строке 7, в правой части задания, 'node [i]' совпадает с 'obj'. Почему вы пишете 'clean (node ​​[i], obj)'? – sawa

+0

, несмотря на странную логику, отмеченную пилой, этот тип кода довольно типичен для обработки гетерогенных структур данных - я не думаю, что это действительно упрощает .... – GreenAsJade

ответ

2

Хотя я не смотрел в рекурсии, я должен прокомментировать тот факт, что вы пишете, если заявления, которые были бы легче читать в сазе:

def clean_node(node) 
    case node 
    when String then clean(node) 
    when Array 
     node.each_with_index do |obj, i| 
     case obj 
      when String 
      node[i] = clean(node[i], obj) 
      else 
      clean_node(obj) 
     end 
     end 
    when Hash.... 
+0

Я также считаю, что случай для String лишний. Все строки будут изменены внутри контейнеров, а 'clean (node)' не изменяет строку на месте. Код можно было бы очистить еще больше, но все это начинает выглядеть как codereview.stackexchange.com. Я думаю, что переход к утверждениям 'case' является хорошим основным советом для удобства чтения. –

+0

Я никогда не знал о codereview.stackexchange.com, спасибо, и да, именно это я и делал. Предложение корпуса очень велико. Подождите, пока @NeilSlater ответит на мой вопрос к его ответу, прежде чем я помету любого в качестве ответа. – Marc

1

Там нет необходимости чтобы разделить обработку строк, вы можете сделать все это в одной рекурсивной подпрограмме, если вы вернете значение node в конце процедуры. Это имеет побочный эффект удаления некоторых параметров, и вы можете использовать на месте .map! для обработки массивов.

Использование case делает выбор по типу немного более легким для чтения.

Добавление способности справляться с массивами строк может быть осуществлено множеством способов. Я решил добавить переменную состояния (общий шаблон в рекурсии, например, для подсчета глубины). Затем в случае массивов рекурсия наследует состояние с текущего уровня, тогда как хэш-регистр определяет новое состояние (для преобразования или нет) на основе поиска в списке ключей для применения преобразований.

def clean_node(node, convert_item = false) 

    case node 

    when String 
     node = node.to_i if convert_item 

    when Array 
     node.map! do |obj| 
     clean_node(obj, convert_item) 
     end 

    when Hash 
     node.each_pair do |key, value| 
     node[key] = clean_node(value, FIXNUM_KEYS.include?(key)) 
     end 
    end 

    node 
end 
+0

Мне это нравится, но вы не проверяете FIXNUM_KEYS и делаете .to_i с любым из объектов массива? – Marc

+0

@Marc: Ваш исходный код, по-видимому, не имел с этим отношения (и с декларативным характером FIXNUM_KEYS означает, что в его использовании должно быть написано * намерение *). На практике я считаю, что чище добавлять обратно в обработку значений String и преобразовывать один уровень рекурсии глубже. –

Смежные вопросы