3

このコードスニペットは@optionsハッシュを設定します。valuesは、Array0個以上の異種アイテムを含むものです。populateエントリである引数を使用して呼び出す場合Hashは、各エントリに指定した値を使用してデフォルト値を想定します。

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ように変更することです。特別な場合があります。キーに入力しようとしている値が、(1)シンボルまたは(2)キーがシンボル(または2つの組み合わせ)であるハッシュのみで構成される配列である場合、それらは次のように扱われる必要があります。そのキーに関連付けられた値ではなくサブキー、および元の引数の評価に使用されたのと同じロジックを再帰的に再適用する必要があります。@optionspopulate

それを言葉にするのは少し難しかったので、私はいくつかのテストケースを書きました。いくつかのテストケースと@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ある種の再帰バージョンに対応するために署名を変更する必要がある場合は、許容されます。理論的に発生する可能性のあるネストの量に制限はありません。

私がこれをどのようにやってのけることができるかについて何か考えはありますか?

4

2 に答える 2

1

だからここに動作するいくつかの簡単なコードがあります。

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は、メソッドの最後の引数がハッシュ(中括弧が指定されていない場合)であると想定しますが、ここで想定しているように、非最終的な引数ではありません。指定されたコードは、ハッシュキーであるpopulateと想定し、の値:cを検索するときに行末を検出するため、(の定義に関係なく)構文エラー:cです。 populate :a, {:b => "apples"}, :c期待どおりに動作します
  • テストケースはをpopulate :a => [:one], :b => [:two, :three => "four"]返します{:a=>{:one=>{}}, :b=>{:two=>{}, :three=>"four"}}。これはテストケースと一致していpopulate :a => [:b]ます。
于 2010-05-25T20:15:06.023 に答える
1

RubyはPerlではなく、=>実際のHash定義内で、またはメソッド呼び出しの最後の引数としてのみ機能します。ほとんどの場合、構文エラーが発生します。

populateRuby構文でサポートされているケースに限定する価値があると確信していますか?

于 2010-07-29T00:05:32.893 に答える