2014-10-07 41 views
0

编写一个接受任意大小的多维容器并将其转换为一维关联数组的函数,该数组的键是表示其值的路径的字符串原来的容器。任意大小的多维容器并将其转换为一维关联数组

所以{ 'one' => {'two' => 3, 'four' => [ 5,6,7]}, 'eight'=> {'nine'=> {'ten'=>11}}}

将成为 : "{'one/two' => 3,'one/four/0' => 5, 'one/four/1' => 6, 'one/four/2' => 7, 'eight/nine/ten' : 11}"

到目前为止,我已经得到了这个...但我有一个很大的问题。任何指向我忽略的东西的指针?

def oneDimHash(hash) 
    if hash.is_a?(Fixnum) 
    puts "AHHH" 
    else 
    hash.each_pair do |key,value| 
     if value.is_a?(Hash) 
     @temp_key << key << '/' 
     oneDimHash(value) 
     elsif value.is_a?(Array) 
     value.each_with_index do |val,index| 
      puts index 
      @temp_key << "#{index}" 
      oneDimHash(val) 
     end 
     else 
     @temp_key << key 
     @result["#{@temp_key}"] = "#{value}" 
     @temp_key = '' 
     end 
    end 
    end 
end 
+1

小心描述一下你想克服的问题吗? – 2014-10-07 19:55:36

回答

0

立即怀疑您使用实例变量而不是方法参数/局部变量。至少,这很可能就是产生了混乱的密钥。假设方法签名不能被修改,你可以通过委托给一个辅助函数来解决对额外参数的需求。也许我会尝试的方法沿着这些线路:

def oneDimHash(o) 
    oneDimHashInternal("", o, {}) 
end 

def oneDimHashInternal(keyStem, o, hash) 
    if o.is_a? Hash 
    o.each_pair do |key, value| 
     oneDimHashInternal("#{keystem}/#{key}", value, hash) 
    end 
    elsif o.is_a? Array 
    # Work this out for yourself 
    else 
    # Store the (non-container) object in hash 
    # Work this out for yourself 
    end 

    hash 
end 

还要注意有Enumerable S中的没有使用数组和哈希。我不知道你是否需要考虑这些。

0

这个怎么样?

def oneDimHash(obj,parent="") 
    unless obj.is_a?(Hash) 
    puts "AHHH" # or may be better: raise "AHHH" 
    else 
    obj.flat_map do |key,value| 
     combined_key = [parent,key.to_s].join '/' 
     case value 
     when Hash then oneDimHash(value,combined_key).to_a 
     when Array then value.each_with_index.map { |v,i| [combined_key+"/#{i}",v] } 
     else [ [combined_key,value] ] 
     end 
    end.to_h 
    end 
end