【问题标题】:How do I implement a tree shaker operation? [closed]如何实现摇树操作? [关闭]
【发布时间】:2013-04-26 01:26:27
【问题描述】:

我需要一个我称之为shake_tree 的操作。我已经使用递归算法实现了它,只使用基本的 ruby-Fortran (引用旧报价“你可以用 any 语言编写 Fortran 代码."),但我怀疑还有一种更简洁和惯用的ruby方式

由于我不知道此操作的通用名称,所以让我简要介绍一下。我有一个像这个例子一样的哈希值:

{
  "-cutoff:" =>
  {
    :flag => {:set_ie1 => [:useCutoff, true]},
    :arg => {:vector_ie1 => :double}
  },
  "-depth:" =>
  {
    :flag => {:set_ie2 => [:useInconsistent, true]},
    :arg => :double,
    :default => 2.0
  },
  "-maxclust:" =>
  {
    :flag => {:set_ie3 => [:useCutoff, false]},
    :arg => {:vector_ie2 => :index}
  },
  :fn => "arrayTypeOptions"
}

在树的结构中嵌入了独特的符号,例如 :vector_ie1:set_ie3。我需要删除树的所有分支,而不是从根到带有符号的叶子的路径。给定上面的例子:

shake_tree(specs, :vector_ie1)

会返回:

{
  "-cutoff:" =>
  {
    :flag => {:set_ie1 => [:useCutoff, true]},
    :arg => {:vector_ie1 => :double}
  }
}

shake_tree(specs, :set_ie2)

会返回:

{
  "-depth:" =>
  {
    :flag => {:set_ie2 => [:useInconsistent, true]},
    :arg => :double,
    :default => 2.0
  }
}

一个更有经验的 ruby 编码员将如何处理这项任务?

【问题讨论】:

  • 为什么不使用像RubyTree 这样的树形库?它有一个parentage 方法可以为您提供这个。
  • @MarkThomas:感谢您的链接,但乍一看,它看起来有点矫枉过正。 ruby DSL 的整个想法是让 ruby 完成大部分工作……现在我的 DSL 的“解析器”包括在“源”上调用 vMATCodeMonkey#instance_eval “ 细绳! :-)

标签: ruby recursion hashmap recursive-datastructures


【解决方案1】:

这是我的递归实现。我决定将其命名为 shake_tree 以保持 RubyMine 的拼写检查器满意(因为我喜欢 shake_tree specs key 的声音):

def shake_tree(specs, key)
  parent = find_parent(specs, key)
  parent ? { parent => specs[parent] } : nil
end

def find_parent(specs, key, keypath = [])
  specs.each do |k, v|
    if k == key
      return (keypath + [k])[0]
    elsif v.is_a?(Hash)
      branch = find_parent(v, key, keypath + [k])
      if !branch.nil?
        return branch
      end
    end
  end
  nil
end

这将完全返回上面指定的输出。

我仍然很想知道这是否有一个通用名称。

【讨论】:

  • 我迟到了 15 秒.. 所以我会在这里粘贴我的答案。抱歉压缩。但是 cmets 很紧
  • 我不完全确定您的数据是否真的是一棵树。这个例子看起来更像是一个 KEY=>ENTRY 形式的结构化数据条目的集合/列表,条目要么是定义良好的结构的简单值。当然,严格来说,它是一棵树,但不仅仅是一棵树 :) 除非您的“条目”比简单值或简单哈希更复杂,否则您可以轻松地过滤 SELECT 或 REJECT 函数没有递归。
  • 示例(数据 = 你的输入数据):data.select{ |key,entry| [:flag,:arg].map {|k| entry[k].keys rescue nil }.flatten.include?( :vector_ie2 ) }
  • 实际上,这几乎是oneliner。注意中间的“:flag, :arg”列表和.include?最后 - 你可能想更好地调整它们。对不起,那个丑陋的救援零,我想保持这个想法简短,而不是“功能齐全”的 responds_to(operator[]) 等等。但是,如果你的键查找可能比以往更深depth=3,那么肯定需要递归和树节点过滤。
  • 顺便说一句。不要误会我的意思:shake_tree 是一个很好的过滤树的操作,我并不强烈建议你用基于列表/集合的过滤来替换它。只需考虑您的确切数据结构并选择最佳匹配项!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 2012-12-12
  • 2018-12-03
  • 2021-09-24
  • 2011-12-13
  • 1970-01-01
相关资源
最近更新 更多