如何展平嵌入式Set和Hash的结构

时间:2015-06-15 04:18:02

标签: ruby recursion

我想将嵌入结构转换为平面结构。

  • 嵌入结构是一组0个或多个对象,例如:字符串或散列,其中一些字符串作为键,另一些嵌入结构作为值。
  • 平面结构是一组数组或字符串。

这里有一些例子:

t(
  Set[]
) # => Set[]

t(
  Set[ 'foo' ]
) # => Set[ ['foo'] ]

t(
  Set[ 'foo0',
       'foo1',
       'foo2' ]
) # => Set[ ['foo0'], ['foo1'], ['foo2'] ]

t(
  Set[ 'foo' => Set[ 'bar' ] ]
) # => Set[ ['foo', 'bar'] ]

t(
  Set[ 'foo' => Set[ 'bar0', 'bar1', 'bar2' ] ]
) # => Set[ ['foo', 'bar0'],
  #         ['foo', 'bar1'],
  #         ['foo', 'bar2'] ]

t(
  Set[ {'foo' => Set[ 'bar0', 'bar1', 'bar2' ]},
       {'FOO' => Set[ 'BAR0', 'BAR1', 'BAR2' ]} ]
) # => Set[ ['foo', 'bar0'],
  #         ['foo', 'bar1'],
  #         ['foo', 'bar2'],
  #         ['FOO', 'BAR0'],
  #         ['FOO', 'BAR1'],
  #         ['FOO', 'BAR2'] ]

t(
  Set[ {'foo' => Set[ {'FOO' => Set[ 'BAR' ]} ]} ]
) # => Set[ ['foo', 'FOO', 'BAR'] ]

t(
  Set[ {'foo' => Set[ {'FOO' => Set[ 'BAR' ]} ]},
       'baz' ]
) # => Set[ ['foo', 'FOO', 'BAR'],
  #         'baz' ]

t(
  Set[ {'foo' => Set[ {'FOO' => Set[ 'BAR0', 'BAR1' ]} ]},
       'baz' ]
) # => Set[ ['foo', 'FOO', 'BAR0'],
  #         ['foo', 'FOO', 'BAR1'],
  #         ['baz'] ]

t(
  Set[ {'foo' => Set[ {'FOO' => Set[ 'BAR0', {'BAR1' => Set[ {'abc' => Set[ 'def' ]} ]} ]} ]},
       'baz' ]
) # => Set[ ['foo', 'FOO', 'BAR0'],
  #         ['foo', 'FOO', 'BAR1', 'abc', 'def'],
  #         ['baz'] ]

我认为我们应该使用电阻率来转换给定的结构。但我不知道实施。请随意使用t函数的任何示例。

修改

换句话说,我想将嵌入结构开发成展平结构

我们可以看到嵌入结构,例如带有因子的表达式。如果我们将它们相乘,则返回展平结构

2 个答案:

答案 0 :(得分:0)

以下是我的t方法的版本:

def t obj
    raise TypeError, "Expecting Hash, Set or Array objects." unless obj.is_a?(Set) || obj.is_a?(Array) || obj.is_a?(Hash)
    recursive = Proc.new do |item|
        case item
        when Set, Hash
            recursive.call( item.to_a )
        when Array
            item.map {|i| recursive.call(i) }
        else
            item
        end
    end
    recursive.call(obj).flatten
end

这很直接,但我不喜欢这么多......我希望以后能想到更好的。

答案 1 :(得分:0)

递归是你的朋友:

require 'set'
def t_h(inp, prefix = [])
    if (inp.is_a?(Hash))
        result = []
        inp.each do |k,v|
            pprefix = prefix.dup
            result << t_h(v, pprefix << k)
        end
        return result.flatten(1)
    elsif (inp.is_a?(Set))
        result = []
        inp.each do |el|
            result << t_h(el, prefix)
        end
        return result.flatten(1)
    else
        pprefix = prefix.dup
        return [ pprefix << inp ]
    end
end

def t(inp)
    Set.new(t_h(inp))
end

# examples
t(Set[ 'foo' => Set[ 'bar' ] ])
t(Set[ 'foo' => Set[ 'bar0', 'bar1', 'bar2' ] ])
t(
  Set[ {'foo' => Set[ 'bar0', 'bar1', 'bar2' ]},
       {'FOO' => Set[ 'BAR0', 'BAR1', 'BAR2' ]} ]
)

代码远非最佳,但你明白了。