在Ruby中使用多参数记忆函数
我想知道是否有一种更“类似于Ruby”的方法可以在Ruby中记忆具有多个参数的函数。我想出了一个可行的方法,但不确定这是否是最好的方法:在Ruby中使用多参数记忆函数,ruby,memoization,Ruby,Memoization,我想知道是否有一种更“类似于Ruby”的方法可以在Ruby中记忆具有多个参数的函数。我想出了一个可行的方法,但不确定这是否是最好的方法: @cache = {} def area(length, width) #Just an example, caching is worthless for this simple function key = [length.to_s, width.to_s].join(',') if @cache[key] puts 'cache hit
@cache = {}
def area(length, width) #Just an example, caching is worthless for this simple function
key = [length.to_s, width.to_s].join(',')
if @cache[key]
puts 'cache hit!'
return @cache[key]
end
@cache[key] = length * width
end
puts area 5, 3
puts area 5, 3
puts area 4, 3
puts area 3, 4
puts area 4, 3
这些参数用逗号连接,逗号用作存储在
@cache
变量中的键。您可以直接使用数组:
def area(length, width)
key = [length, width]
if @cache[key]
puts 'cache hit!'
return @cache[key]
end
@cache[key] = length * width
end
或使用嵌套哈希:
def area(length, width)
c = (@cache[length] ||= {})
if c[width]
puts 'cache hit!'
return c[width]
end
c[width] = length * width
end
当您不需要打印
缓存时,点击代码>然后我会这样做:
def area(length, width)
@cache ||= {}
@cache["#{length},#{width}"] ||= length * width
end
def area(*args)
@cache ||= {}
@cache[args] ||= args.inject(:*)
end
或者如果您需要一些输出,但是缓存未命中代码>也可以:
def area(length, width)
@cache ||= {}
@cache.fetch("#{length},#{width}") do |key|
puts 'Cache miss!'
@cache[key] = length * width
end
end
如果您想要接受更多的参数,您可能需要使用如下内容:
def area(length, width)
@cache ||= {}
@cache["#{length},#{width}"] ||= length * width
end
def area(*args)
@cache ||= {}
@cache[args] ||= args.inject(:*)
end
在Ruby 2.7及更高版本上,位置参数和关键字参数是隔离的,这对如何实现多参数记忆有影响。对于一般实现,我将执行以下操作:
def area(length, width)
@cache ||= {}
@cache["#{length},#{width}"] ||= length * width
end
def area(*args)
@cache ||= {}
@cache[args] ||= args.inject(:*)
end
def my_方法(*args,**kwargs)
(@my_method_cache | |={})[args.hash^kwargs.hash]| |=开始
(...)
结束
结束
将(…)
替换为使用我的_方法所做的昂贵计算
我会对所有这些方法的线程安全性感到紧张,但尤其是最后一个。第一个方法的妙招。那么数组会自动转换为字符串吗?线程到底有什么问题?什么会出错?将生成两种不同的缓存数据结构?不,数组不会自动转换为字符串。没有必要这样做。因为每个对象都可以用作哈希键:符号、整数,甚至是庞大复杂的数据结构。。。但是使用嵌套的哈希表,一个调用可以清除不同宽度的计算(对于相同的长度),例如,我做了一些基准测试。我原来使用连接的函数的速度是使用对象作为键的速度的两倍。有没有一种自动生成密钥的好方法?即使去掉print语句,您的代码也比我的代码快2倍。您的意思是,如果您使用常用命名参数,但不想全部列出它们?也许有个办法:看看这个。但我会用它…我想它应该是硬编码的。那看起来很难看。有处理多参数记忆的Ruby gem吗?如果性能有问题,散列参数并使用整数作为键会更好。类似于length.hash^width.hash
。它还可以很容易地适应于处理可变数量的参数:args.inject{| r,n | r^n.hash}
。哈希冲突的可能性非常小。你总是可以加入一个素数来降低这些几率。