从哈希

时间:2015-06-10 15:47:21

标签: ruby

class KeyServer

的一部分
@generated_keys = Hash.new

def generate_key
    key = SecureRandom.urlsafe_base64
    while(purged_keys.include?(key))
      key = SecureRandom.urlsafe_base64
    end
    #add new key to hashes that maintain records
    @generated_keys.merge!({key => Time.now})
    @all_keys.merge!(@generated_keys) { |key, v1, v2| v1 }
    return key
  end

我在这里使用生成的密钥:(我需要一个随机对来选择并分配给用户)

def get_available_key
    if(generated_keys.empty?)
      return "404. No keys available"
    else
      new_key = @generated_keys.to_a.sample(1)
      @generated_keys.delete(new_key[0][0].to_s)
      @blocked_keys.merge!({new_key[0][0].to_s => Time.now})
    end
  end

这是我在Sinatra

中使用它的方式
api = KeyServer.new
get '/block_key' do 
  api.get_available_key
end

我尝试了此question中提到的解决方案,但当我将其作为Sinatra服务器的一部分运行时,我获得了Internal Server Error: No implicit conversion from Array to String

如何使这项工作?任何其他从Hash获得随机对的方法都是受欢迎的。

2 个答案:

答案 0 :(得分:1)

hash.to_a.sample求值为一个双元素数组,其中第一个元素是某个键,第二个元素是相应的值。

当您致电删除时,您应使用hash.delete(new_key[0])代替hash.delete(new_key[0][0].to_s)

答案 1 :(得分:1)

要从Hash获取一个随机元素作为Hash返回,您可以简单地修补Hash来执行此操作

class Hash
  def sample(n)
    Hash[to_a.sample(n)]
  end
end

然后像

一样打电话
h = {a: 1, b: 2, c: 3} 
h.sample(1)
#=> {b: 2}
h.sample(2) 
#=> {:b=>2, :a=>1}

注意:我在Ruby 2.X中使用Hash::[]用于兼容性目的,您可以使用to_h代替。

除此之外,我认为您的代码可能会出现一些问题,而且它们的返回值也是如此。

如果我要重构你的代码,那么就不需要上面的示例代码了,我会改用类似

的东西。
def get_available_key
  if(generated_keys.empty?)
    {"error" => "404. No keys available"}
  else
    new_key = @generated_keys.keys.sample(1)
    @generated_keys.delete(new_key)
    @blocked_keys.merge!({new_key => Time.now})[new_key]
  end
end

这样它总是会响应Hash对象进行处理,而且根本不用担心多维数组。

我还会将初始代码更改为更像

def create_new_key 
  key = SecureRandom.urlsafe_base64
  purged_keys.include?(key) ? create_new_key  : key
end
def generate_key
  key = create_new_key 
  #add new key to hashes that maintain records
  @generated_keys.merge!({key => Time.now})
  @all_keys.merge!(@generated_keys) { |key, v1, v2| v1 }
  key
end
def add_to_key_chain(length)
  @generated_keys ||= {}
  length.times do 
    create_new_key
  end
end

虽然我不知道purged_keys方法是什么样的。