将数组数组转换为数组和散列的组合

时间:2016-12-19 15:10:24

标签: ruby tree

我一直在尝试将数组数组转换为数组和哈希的组合。让我解释一下我想要实现的目标:

输入:

[['a'], ['b'], ['a', 'b', 'c'], ['a', 'b', 'd']]

预期输出:

[:a => [{:b => [:c, :d]}], :b]

到目前为止我想出的是:

def converter(array)
  tree_hash = {}

  array.each do |path|
    path.each_with_index.inject(tree_hash) do |node, (step, index)|
      step = step.to_sym

      if index < path.size - 1
        node[step] ||= {}
      else
        node[step] = nil
      end
    end
  end

  tree_hash
end

它给了我以下结果:

converter([['a'], ['b'], ['a', 'b', 'c'], ['a', 'b', 'd']])
=> {:a=>{:b=>{:c=>nil, :d=>nil}}, :b=>nil} 

任何人都可以抛光,以便我可以解决这个问题。这个问题是否有任何名称,直接图/间接图/图论?我愿意学习和提高我对图形和树木的知识。

如果您帮我解决这个问题或者给我一些如何解决这个问题的说明,我将不胜感激。

感谢。

2 个答案:

答案 0 :(得分:3)

def group_by_prefix(elements)
  elements.group_by(&:first).map do |prefix, elements|
    remainders = elements.map { |element| element.drop(1) }.reject(&:empty?)

    if remainders.empty?
      prefix.to_sym
    else
      {prefix.to_sym => group_by_prefix(remainders)}
    end
  end
end

foo = [['a'], ['b'], ['a', 'b', 'c'], ['a', 'b', 'd']]
group_by_prefix(foo) # => [{:a=>[{:b=>[:c, :d]}]}, :b]

答案 1 :(得分:1)

它看起来与Trie非常相似。

此结构通常与字符串('apple'一起使用,被视为字符数组:%w(a p p l e)),但可以轻松修改它以接受字符串数组(%w(bar car)) :

class Node
  attr_reader :key, :children
  def initialize(key, children = [])
    @key = key
    @children = children
  end

  def to_s
    key.to_s
  end

  def to_sym
    key.to_sym
  end
end

class Trie
  attr_reader :root
  def initialize
    @root = Node.new('')
  end

  def self.from_array(array)
    array.each_with_object(Trie.new) { |letters, trie| trie.add(letters) }
  end

  def add(letters)
    node = root
    letters.each do |c|
      next_node = node.children.find { |child| child.key == c }
      if next_node
        node = next_node
      else
        next_node = Node.new(c)
        node.children.push(next_node)
        node = next_node
      end
    end
  end

  def show(node = root, indent = 0)
    puts '  ' * indent + node.to_s
    node.children.each do |child|
      show(child, indent + 1)
    end
  end

  def to_arrays_and_hashes
    recursive_to_arrays_and_hashes(root)[root.to_sym]
  end

  private

  def recursive_to_arrays_and_hashes(node)
    if node.children.empty?
      node.to_sym
    else
      {node.to_sym => node.children.map{|c| recursive_to_arrays_and_hashes(c)}}
    end
  end
end

array1 = [['a'], ['b'], ['a', 'b', 'c'], ['a', 'b', 'd']]
array2 = [['foo'], ['bar', 'car']]

[array1, array2].each do |array|
  trie = Trie.from_array(array)
  trie.show
  p trie.to_arrays_and_hashes
end

它返回:

  a
    b
      c
      d
  b
[{:a=>[{:b=>[:c, :d]}]}, :b]

  foo
  bar
    car
[:foo, {:bar=>[:car]}]