我有一个哈希,它有一个未知的集合和嵌套数组、哈希、哈希数组和字符串的混合。这是JSON.parse
的结果。数据的结构必须与开始时相同。最终目标是将字符串转换为可能是 Fixnum 的 Fixnum。
以下内容工作正常,但我想知道是否可以缩短它。请注意我如何需要 clean
方法中的键和值,因为并非所有可以是 Fixnum 的字符串都应该如此。有什么想法吗?
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
无需拆分字符串处理,如果您在例程末尾返回 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
虽然我没有研究递归,但我必须评论你正在编写 if 语句的事实,这些语句在 case 语句中更容易阅读:
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....