4

この質問は、パラメーターを変更する可能性がある非常に特殊なケースに関するものです。これは Rails アプリの一部ではありません。

params は{:email => " ab", :xyz => " ", :opq => nil} 次のように実行します:

params.each{|_, v| v.strip! if v}
params.keep_if{|_, v| v.length > 0 if v}

パラメータを取得する {:email => "ab"}

上記の 2 行を 1 つにマージする方法はありますか?

4

5 に答える 5

4
ruby-1.9.3-p125 :011 > params ={:email => " ab", :xyz => " ", :opq => nil}
 => {:email=>" ab", :xyz=>" ", :opq=>nil} 
ruby-1.9.3-p125 :012 > params.reject! { |_, v| !v || v.strip!.length == 0 }
 => {:email=>"ab"}
于 2012-11-13T21:37:13.803 に答える
1
params.each{|_, v| v.strip! if v}.reject!{|_, v| !v || v.length == 0}
于 2012-11-13T21:33:01.180 に答える
0

これは技術的にあなたの質問に答えるように見える1つのオプションですが、あなたが探しているものではないと思います:

params.select{|_,v| v.strip.length > 0 if v}

あなたが直面している根本的な問題は、Hash#map がハッシュではなく配列を返すことです。私を含め、多くの人がこれを煩わしいと感じています。例を参照してください: http://www.ruby-forum.com/topic/185611

これは、inject を使用した冗長オプションです。

params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}

あなたにとって重要な場合、これらのソリューションのどちらもパラメーターに破壊的な変更を加えることはありません。

1.9.3-p125 :030 > params = {:email => " ab", :xyz => " ", :opq => nil}
 => {:email=>" ab", :xyz=>" ", :opq=>nil} 
1.9.3-p125 :031 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v|   v.length > 0 if v}
 => {:email=>"ab"} 
1.9.3-p125 :032 > params
 => {:email=>" ab", :xyz=>" ", :opq=>nil} 

Inject は、慣れが必要なトリッキーな機能です。この行を順を追って説明します。

  • params.inject({}}結果を格納するための空のハッシュを作成するように指示します。
  • |h, (k,v)| 新しい空のハッシュを変数 h に渡すと同時に、元の params ハッシュのキーと値のペアをそれぞれ k、v に渡すように指示します。

次に毛むくじゃらです。次のコマンドを内側から展開します。

  • v ? v.strip : v三項演算子を使用して、v が true と評価される場合に v.strip を返し、v が false または nil の場合に v を返します。

  • k => v ? v.strip : v結果で新しいハッシュを作成します

  • h.merge(k => v ? v.strip : v)新しいハッシュを h にマージします。h は空で始まり、結果を注入ループの次の反復に渡します。

  • ループの次の繰り返しでは、 h は空ではなくなり、将来の結果は引き続き h にマージされます。

この時点で、ハッシュを削除しました。ここで停止すると、結果は次のようになります。

1.9.3-p125 :032 > params
 => {:email=>" ab", :xyz=>" ", :opq=>nil} 
1.9.3-p125 :033 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}
 => {:email=>"ab", :xyz=>"", :opq=>nil} 

ハッシュが削除されたので、select ステートメントは簡単です。ここでは、keep_if ではなく select を使用します。なぜなら、! がないにもかかわらず、keep_if は破壊的なメソッドだからです。この暴言を参照してください: http://news.ycombinator.com/item?id=2247352 . inject ステートメントはハッシュを返すので、それを直接呼び出すことができますが.select、実際にはコード行をこれほど長くすることはお勧めしません。

1.9.3-p125 :034 > params
 => {:email=>" ab", :xyz=>" ", :opq=>nil} 
1.9.3-p125 :035 > params.inject({}) {|h,(k,v)| h.merge(k => v ? v.strip : v)}.select{|_,v| v.length > 0 if v}
 => {:email=>"ab"} 
于 2012-11-13T23:21:31.633 に答える
0
params.keys.each{|k| v = h.delete(k); h[k] = v.strip if v and !v.empty?}

また

params.select!{|k, v| v and v.strip!; v and !v.empty?}
于 2012-11-13T23:58:45.843 に答える
0

実際、あなたが書いた行は連鎖可能です:

params.each{|_, v| v.strip! if v}.keep_if{|_, v| v.length > 0 if v}

これeachは、(更新された) オブジェクト自体を返すため機能します。ただし、私見のインプレース更新は通常悪い考えであるため、機能的なアプローチを次に示します。

params2 = Hash[params.map { |k, v| [k, v.strip] if v && v.strip.size > 0 }.compact]

しかし、stdlib にはいくつかの基本的な抽象化が欠けているため、これは不必要に冗長です。の助けを借りて、Enumerable#mashObject#present?のように簡単です。

params2 = params.mash { |k, v| [k, v.strip] if v.present? }
于 2012-11-13T21:53:59.923 に答える