我有一个这样的散列:

params = { :irrelevant => "A String",
           :choice1 => "Oh look, another one",
           :choice2 => "Even more strings",
           :choice3 => "But wait",
           :irrelevant2 => "The last string" }

我想要一个简单的方法来拒绝所有不是choice+int的键。可以是choice1,或者从choice1到choice10。它变化。

我如何用单词选择和后面的一个或多个数字来挑选键?

奖金:

将散列转换为以tab (\t)作为分隔符的字符串。我这样做了,但它花了几行代码。通常大师级的卢比手可以在一行或几行内完成。


当前回答

params.select{ |k,v| k =~ /choice\d/ }.map{ |k,v| v}.join("\t")

其他回答

关于奖金问题:

If you have output from #select method like this (list of 2-element arrays): [[:choice1, "Oh look, another one"], [:choice2, "Even more strings"], [:choice3, "But wait"]] then simply take this result and execute: filtered_params.join("\t") # or if you want only values instead of pairs key-value filtered_params.map(&:last).join("\t") If you have output from #delete_if method like this (hash): {:choice1=>"Oh look, another one", :choice2=>"Even more strings", :choice3=>"But wait"} then: filtered_params.to_a.join("\t") # or filtered_params.values.join("\t")

与散列::选择:

params = params.select { |key, value| /^choice\d+$/.match(key.to_s) }

最简单的方法是包含gem 'activesupport'(或gem 'active_support')。

参数个数。切片(:choice1,:choice2,:choice3)

最简单的方法是包含gem 'activesupport'(或gem 'active_support')。

然后,在你的课上你只需要

require 'active_support/core_ext/hash/slice'

然后打电话

params.slice(:choice1, :choice2, :choice3) # => {:choice1=>"Oh look, another one", :choice2=>"Even more strings", :choice3=>"But wait"}

我认为声明其他可能有bug的函数是不值得的,最好使用在过去几年里调整过的方法。

这是一条解决完整原始问题的直线:

params.select { |k,_| k[/choice/]}.values.join('\t')

但是上面的大多数解决方案都是使用slice或简单的regexp来解决需要提前知道键的情况。

下面是另一种适用于简单和更复杂用例的方法,它在运行时是可切换的

data = {}
matcher = ->(key,value) { COMPLEX LOGIC HERE }
data.select(&matcher)

现在,这不仅允许在匹配键或值时使用更复杂的逻辑,而且也更容易测试,并且可以在运行时交换匹配逻辑。

解决原问题:

def some_method(hash, matcher) 
  hash.select(&matcher).values.join('\t')
end

params = { :irrelevant => "A String",
           :choice1 => "Oh look, another one",
           :choice2 => "Even more strings",
           :choice3 => "But wait",
           :irrelevant2 => "The last string" }

some_method(params, ->(k,_) { k[/choice/]}) # => "Oh look, another one\\tEven more strings\\tBut wait"
some_method(params, ->(_,v) { v[/string/]}) # => "Even more strings\\tThe last string"