我一直在尝试将数组数组转换为数组和哈希的组合。让我解释一下我想要实现的目标:
输入:
[['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}
任何人都可以抛光,以便我可以解决这个问题。这个问题是否有任何名称,直接图/间接图/图论?我愿意学习和提高我对图形和树木的知识。
如果您帮我解决这个问题或者给我一些如何解决这个问题的说明,我将不胜感激。
感谢。
答案 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]}]