2009-11-16 52 views
0

我最近做了一个类的任务,我做了一个非常黑客的数据结构。我最终使用了嵌套散列,这似乎是一个好主意,但是很难遍历和管理。在ruby中优雅地处理数据结构(哈希等)

我在做一般的东西,就像一个标签映射到物品的散列,映射到价格和类似的东西。但其中一些变得越来越复杂。

我知道,铁轨使用了很多更优雅的看似东西与符号等(我从来没有使用可耻的脸),我想知道如何可以优化这一点。例如,如果我有我的嵌套散列这样的东西

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

有没有一种优雅的方式拉出这些值?也许我只是这方面的一个新手,但我想在开始做更多事情之前设置好事情。也许我甚至在寻找不同的东西,比如数组/混编或其他东西。请告诉我!

+0

这是一个有趣的问题要回答,谢谢你的提问。 :-) – 2009-11-16 21:14:05

回答

0
h["cool"].keys 

到然后循环树是

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

当然,我正在做这样的事情,我想。但它非常麻烦,如果你需要多达5个嵌套数组呢? – 2009-11-16 20:41:07

+0

@Stacia然后你写一个递归版本。 – EmFi 2009-11-16 21:13:31

3

看起来你需要考虑更严格的结构化数据。尝试为您的物品创建一个类,这些类可以包含其他物品的价格,也可以按照您访问它们的方式组织它们。想想你想要什么,并以一种对你有意义的方式将信息放置在结构中。如果您需要扩展系统并找不到,其他任何事情都会浪费时间,无论是现在还是三个月。

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

+0

免责声明:抛出本季度的课程;) 如果我有时间或它在下一个任务上变得可怕,我可能会尝试类似的东西。 – 2009-11-16 20:42:20

+0

红宝石纯粹是面向对象的。 Ruby中的类实际上并不像其他语言中的那么多。你可能会得到一个大部分为空的类和一个attr_accessors列表。 – EmFi 2009-11-16 21:15:06

+0

甚至打开 – 2009-11-17 09:01:18

0

这实际上取决于你想要做什么(在问题中没有足够的信息),但是如果你需要潜入三个或更多级别到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是你想要做什么是最好的数据结构?

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 

Cheerio!