gpt4 book ai didi

ruby - 如何根据提供的参数在 Ruby 中递归定义哈希?

转载 作者:数据小太阳 更新时间:2023-10-29 08:06:25 24 4
gpt4 key购买 nike

这段代码填充了一个@options 散列。 values 是一个 Array,其中包含零个或多个异构项。如果您使用作为 Hash 条目的参数调用 populate,它会使用您为每个条目指定的值来假定默认值。

def populate(*args)
args.each do |a|
values = nil
if (a.kind_of? Hash)
# Converts {:k => "v"} to `a = :k, values = "v"`
a, values = a.to_a.first
end

@options[:"#{a}"] ||= values ||= {}
end
end

我想做的是更改populate,使其递归填充@options。有一种特殊情况:如果它要填充键的值是一个数组,该数组完全由(1)符号或(2)键为符号(或两者的某种组合)的哈希组成,则应将它们视为subkeys 而不是与该键关联的值,并且应该递归地重新应用用于评估原始 populate 参数的相同逻辑。

这有点难以用语言表达,所以我写了一些测试用例。以下是一些测试用例和 @options 之后的期望值:

populate :a
=> @options is {:a => {}}

populate :a => 42
=> @options is {:a => 42}

populate :a, :b, :c
=> @options is {:a => {}, :b => {}, :c => {}}

populate :a, :b => "apples", :c
=> @options is {:a => {}, :b => "apples", :c => {}}

populate :a => :b
=> @options is {:a => :b}

# Because [:b] is an Array consisting entirely of Symbols or
# Hashes whose keys are Symbols, we assume that :b is a subkey
# of @options[:a], rather than the value for @options[:a].
populate :a => [:b]
=> @options is {:a => {:b => {}}}

populate :a => [:b, :c => :d]
=> @options is {:a => {:b => {}, :c => :d}}

populate :a => [:a, :b, :c]
=> @options is {:a => {:a => {}, :b => {}, :c => {}}}

populate :a => [:a, :b, "c"]
=> @options is {:a => [:a, :b, "c"]}

populate :a => [:one], :b => [:two, :three => "four"]
=> @options is {:a => :one, :b => {:two => {}, :three => "four"}}

populate :a => [:one], :b => [:two => {:four => :five}, :three => "four"]
=> @options is {:a => :one,
:b => {
:two => {
:four => :five
}
},
:three => "four"
}
}

如果 populate 的签名需要更改以适应某种递归版本,这是可以接受的。理论上可以发生的嵌套数量没有限制。

关于如何实现这一点有什么想法吗?

最佳答案

所以这里有一些简单的代码可以工作。

def to_value args
ret = {}
# make sure we were given an array
raise unless args.class == Array
args.each do |arg|
case arg
when Symbol
ret[arg] = {}
when Hash
arg.each do |k,v|
# make sure that all the hash keys are symbols
raise unless k.class == Symbol
ret[k] = to_value v
end
else
# make sure all the array elements are symbols or symbol-keyed hashes
raise
end
end
ret
rescue
args
end
def populate *args
@options ||= {}
value = to_value(args)
if value.class == Hash
@options.merge! value
end
end

它确实偏离了你的测试用例:

  • 测试用例 populate :a, :b => "apples", :c是 ruby​​ 语法错误。 Ruby 将假设方法的 final 参数是散列(当没有给出大括号时),但不是非最终参数,正如您在这里假设的那样。给定的代码是一个语法错误(无论 populate 的定义如何)因为它假设 :c是一个散列键,在查找 :c 时找到行尾的值(value)。 populate :a, {:b => "apples"}, :c按预期工作
  • 测试用例 populate :a => [:one], :b => [:two, :three => "four"]返回 {:a=>{:one=>{}}, :b=>{:two=>{}, :three=>"four"}} .这与测试用例 populate :a => [:b] 一致.

关于ruby - 如何根据提供的参数在 Ruby 中递归定义哈希?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2901041/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com