[英]Iterate over just some elements of a Hash in Ruby
I've got a Hash that looks like this: 我有一个看起来像这样的哈希:
card = {
name: "Mrs.Jones",
number: "4242 4242 4242 4242",
exp_month: "12",
exp_year: "2014",
address: "90210 Beverly Hills",
added: "2014-11-09 09:14:23"
}
I'd like to iterate over just the number
, exp_month
and exp_year
fields and update them. 我只想遍历number
, exp_month
和exp_year
字段并更新它们。 What's the most Ruby-like way of doing that? 最像Ruby的方式是什么?
This is what my code looks like at present: 这是我的代码目前的样子:
card.each do |key,value|
card[key] = encrypt(value) # Only apply to number, exp_month and exp_year
end
I'd do it the following way: 我将通过以下方式进行操作:
ENCRYPTED_FIELDS = [:number, :exp_month, :exp_year]
card.each do |key,value|
card[key] = encrypt(value) if ENCRYPTED_FIELDS.include?(key)
end
But a better option would be to make a class for CreditCardDetails and define the setters to encrypt the data: 但是更好的选择是为CreditCardDetails创建一个类并定义设置器以加密数据:
class CreditCardDetails
def initialize(hash)
hash.each do |k, v|
self.send("#{k}=", v)
end
end
#example for not encrypted field
def name=(value)
@name = value
end
#example for encrypted field
def number=(value)
@number = encrypted(value)
end
end
Since you already know which keys you'd like to encrypt, you can iterate over the wanted key names, instead of the hash: 由于您已经知道要加密的密钥,因此可以遍历所需的密钥名称,而不是哈希:
ENCRYPTED_FIELDS = [:number, :exp_month, :exp_year]
ENCRYPTED_FIELDS.each do |key|
card[key] = encrypt(card[key])
end
Here are a couple of ways to do it. 这有两种方法。 I've replaced the method encrypt
with size
, for purposes of illustration. 为了说明起见,我用size
替换了encrypt
方法。 They both use the form of Hash#merge that takes a block. 它们都使用带一个块的Hash#merge形式。 The second approach does not use keys. 第二种方法不使用键。 Instead, it processes the value if the value is all digits (and spaces). 相反,如果值是所有数字(和空格),它将处理该值。 I included that mainly to illustrate what you might do in other applications. 我将其包括在内主要是为了说明您可能在其他应用程序中执行的操作。
#1 #1
card.merge(card) do |k,_,v|
case k
when :number, :exp_month, :exp_year
v.size
else
v
end
end
#=> {:name=>"Mrs.Jones", :number=>19, :exp_month=>2, :exp_year=>4,
# :address=>"90210 Beverly Hills", :added=>"2014-11-09 09:14:23"}
#2 #2
card.merge(card) { |*_,v| v[/^[\s\d]+$/] ? v.size : v }
#=> {:name=>"Mrs.Jones", :number=>19, :exp_month=>2, :exp_year=>4,
# :address=>"90210 Beverly Hills", :added=>"2014-11-09 09:14:23"}
If you want to mutate card
, use Hash#update (aka merge!
) rather than merge
: 如果您想对card
进行变异,请使用Hash#update (又名merge!
)而不是merge
:
#1a #1a
card.update(card) do |k,_,v|
case k
when :number, :exp_month, :exp_year
v.size
else
v
end
end
#=> {:name=>"Mrs.Jones", :number=>19, :exp_month=>2, :exp_year=>4,
# :address=>"90210 Beverly Hills", :added=>"2014-11-09 09:14:23"}
card
#=> {:name=>"Mrs.Jones", :number=>19, :exp_month=>2, :exp_year=>4,
# :address=>"90210 Beverly Hills", :added=>"2014-11-09 09:14:23"}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.