【问题标题】:handling data structures (hashes etc) gracefully in ruby在 ruby​​ 中优雅地处理数据结构(哈希等)
【发布时间】:2010-12-17 04:42:50
【问题描述】:

我最近做了一个课堂作业,我做了一个非常 hacky 的数据结构。我最终使用了嵌套哈希,这似乎是个好主意,但很难迭代和管理。

我在做一般的事情,比如一个标签映射到一个映射到价格的项目散列和类似的东西。但其中一些变得越来越复杂。

我知道 Rails 使用了很多看起来更优雅的符号和类似的东西(我从不使用可耻的脸),我想知道如何优化它。例如,如果我有类似这样的嵌套哈希

 h["cool"][????][1.2]

有没有一种优雅的方式来提取这些值?也许我在这方面只是一个新手,但我想在开始做更多事情之前把事情弄清楚。也许我什至在寻找不同的东西,比如数组/哈希的混合或其他东西。请告诉我!

【问题讨论】:

  • 这是一个有趣的问题,感谢您的提问。 :-)

标签: ruby data-structures hash dictionary


【解决方案1】:

您似乎需要考虑更严格地构建数据结构。尝试为您的项目创建一个类,其中可以包含价格等,并且可能以您需要访问它们的方式组织它们。想想你想要什么,并以对你有意义的方式将信息放在结构中。其他任何事情都是浪费时间,无论是现在还是三个月后,当您需要扩展系统却发现无法扩展时。

是的,这将是相当多的工作,是的,这是值得的。

【讨论】:

  • 免责声明:本季度的课程;)如果我有时间或者下一个作业变得很糟糕,我可以尝试类似的方法。
  • Ruby 是纯面向对象的。 ruby 中的类确实不如其他语言中的工作量大。您可能可以使用一个大部分为空的类和一个 attr_accessors 列表。
【解决方案2】:

编辑:修改为提供该项目的粗略路径。但是它不知道变量的名称。

试试这个:

def iterate_nested(array_or_hash, depth = [], &block)
  case array_or_hash
    when Array:
      array_or_hash.each_with_index do |item, key|
        if item.class == Array || item.class == Hash
          iterate_nested(item, depth + [key], &block)
        else
          block.call(key, item, depth + [key])
        end
      end
    when Hash:
      array_or_hash.each do |key, item|
        if item.class == Array || item.class == Hash
          iterate_nested(item, depth + [key], &block)
        else
          block.call(key, item, depth + [key])
        end
      end
  end
end

它应该迭代到任何必要的深度,受内存等限制,并返回键和项以及返回项的深度。适用于哈希和数组。

如果你测试:

iterate_nested([[[1,2,3], [1,2,3]], [[1,2,3], [1,2,3]], [[1,2,3], [1,2,3]]]) do |key, item, depth|
  puts "Element: <#{depth.join('/')}/#{key}> = #{item}"
end

它产生:

Element: <0/0/0/0> = 1
Element: <0/0/1/1> = 2
Element: <0/0/2/2> = 3
Element: <0/1/0/0> = 1
Element: <0/1/1/1> = 2
Element: <0/1/2/2> = 3
Element: <1/0/0/0> = 1
Element: <1/0/1/1> = 2
Element: <1/0/2/2> = 3
Element: <1/1/0/0> = 1
Element: <1/1/1/1> = 2
Element: <1/1/2/2> = 3
Element: <2/0/0/0> = 1
Element: <2/0/1/1> = 2
Element: <2/0/2/2> = 3
Element: <2/1/0/0> = 1
Element: <2/1/1/1> = 2
Element: <2/1/2/2> = 3

干杯!

【讨论】:

    【解决方案3】:
    h["cool"].keys
    

    然后迭代树将是

    h["cool"].keys.each |outer| { h["cool"][outer].each { |inner| puts inner }}
    

    【讨论】:

    • 当然,我想我正在做类似的事情。但这很麻烦,如果你需要最多 5 个的嵌套数组呢?
    • @Stacia 然后你写一个递归版本。
    【解决方案4】:

    这实际上取决于您要执行的操作(问题中的信息还远远不够),但是如果您需要深入到 Hash 的三个或更多级别,您可能非常需要递归树遍历算法:

    def hash_traverse(hash)
      result = ""
      for key, value in hash
        result << key.to_s + ":\n"
        if !value.kind_of?(Hash)
          result << "  " + value.to_s + "\n"
        else
          result << hash_traverse(value).gsub(/^/, "  ")
        end
      end
      return result
    end
    

    您确定 Hash 是您尝试做的最佳数据结构吗?

    【讨论】:

      猜你喜欢
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      • 2011-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-09
      • 2011-05-07
      相关资源
      最近更新 更多