在Ruby中记忆具有多个参数的函数

时间:2018-08-14 17:57:46

标签: 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!'
    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变量中的键。

3 个答案:

答案 0 :(得分:5)

当您不需要打印Cache hit!时,我会执行以下操作:

def area(length, width)
  @cache ||= {}
  @cache["#{length},#{width}"] ||= length * width
end

或者如果您需要一些输出,但是也可以使用Cache miss!

def area(length, width)
  @cache ||= {}

  @cache.fetch("#{length},#{width}") do |key| 
    puts 'Cache miss!'
    @cache[key] = length * width
  end
end

如果您想接受更多的参数,则可能需要使用以下内容:

def area(*args)
  @cache ||= {}
  @cache[args] ||= args.inject(:*)
end

答案 1 :(得分:3)

您可以直接使用数组:

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

答案 2 :(得分:0)

Ruby 2.7及更高版本上,位置参数和关键字参数是隔离的,这对实现多参数备注的方式有影响。对于一般的实现,我会做这样的事情:

def my_method(*args, **kwargs)
  (@my_method_cache ||= {})[args.hash ^ kwargs.hash] ||= begin
    (...)
  end
end

(...)完成的昂贵计算替换my_method