任何大小的多维容器,并将其转换为一维关联数组

时间:2014-10-07 19:45:54

标签: ruby arrays recursion hash

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

所以{ '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

2 个答案:

答案 0 :(得分: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既不是数组也不是哈希。我不知道你是否需要考虑这个问题。

答案 1 :(得分: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