gpt4 book ai didi

ruby - 为特定值切片参数散列

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

总结

给定一个哈希,根据要使用的键列表创建子集哈希的最有效方法是什么?

h1 = { a:1, b:2, c:3 }        # Given a hash...
p foo( h1, :a, :c, :d ) # ...create a method that...
#=> { :a=>1, :c=>3, :d=>nil } # ...returns specified keys...
#=> { :a=>1, :c=>3 } # ...or perhaps only keys that exist

详情

Sequel数据库工具包允许通过传入哈希来创建或更新模型实例:

foo = Product.create( hash_of_column_values )
foo.update( another_hash )

Sinatra Web 框架提供了一个名为 params 的哈希,其中包括表单变量、查询字符串参数以及路由匹配项。

如果我创建一个仅包含与数据库列同名的字段的表单并将其发布到此路由,一切都会非常方便:

post "/create_product" do
new_product = Product.create params
redirect "/product/#{new_product.id}"
end

然而,这既脆弱又危险。这很危险,因为恶意黑客可能会发布一个包含不打算更改的列的表单并更新它们。它很脆弱,因为在这条路线上使用相同的形式是行不通的:

post "/update_product/:foo" do |prod_id|
if product = Product[prod_id]
product.update(params)
#=> <Sequel::Error: method foo= doesn't exist or access is restricted to it>
end
end

因此,为了稳健性和安全性,我希望能够这样写:

post "/update_product/:foo" do |prod_id|
if product = Product[prod_id]
# Only update two specific fields
product.update(params.slice(:name,:description))
# The above assumes a Hash (or Sinatra params) monkeypatch
# I will also accept standalone helper methods that perform the same
end
end

...而不是更冗长和非 DRY 选项:

post "/update_product/:foo" do |prod_id|
if product = Product[prod_id]
# Only update two specific fields
product.update({
name:params[:name],
description:params[:description]
})
end
end

更新:基准

以下是对(当前)实现进行基准测试的结果:

                    user     system      total        real
sawa2 0.250000 0.000000 0.250000 ( 0.269027)
phrogz2 0.280000 0.000000 0.280000 ( 0.275027)
sawa1 0.297000 0.000000 0.297000 ( 0.293029)
phrogz3 0.296000 0.000000 0.296000 ( 0.307031)
phrogz1 0.328000 0.000000 0.328000 ( 0.319032)
activesupport 0.639000 0.000000 0.639000 ( 0.657066)
mladen 1.716000 0.000000 1.716000 ( 1.725172)

@sawa 的第二个答案是最快的,比我基于 tap 的实现(基于他的第一个答案)还差一步。选择添加对 has_key? 的检查只会增加很少的时间,而且速度仍然是 ActiveSupport 的两倍多。

这是基准代码:

h1 = Hash[ ('a'..'z').zip(1..26) ]
keys = %w[a z c d g A x]
n = 60000

require 'benchmark'
Benchmark.bmbm do |x|
%w[ sawa2 phrogz2 sawa1 phrogz3 phrogz1 activesupport mladen ].each do |m|
x.report(m){ n.times{ h1.send(m,*keys) } }
end
end

最佳答案

我只会使用 active_support 提供的 slice 方法

require 'active_support/core_ext/hash/slice'
{a: 1, b: 2, c: 3}.slice(:a, :c) # => {a: 1, c: 3}

当然,请确保更新您的 gemfile:

gem 'active_support'

关于ruby - 为特定值切片参数散列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5652976/

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