【问题标题】:Using Ruby, what is the most efficient way to check if any key in a hash matches any values within an Array使用 Ruby,检查哈希中的任何键是否与数组中的任何值匹配的最有效方法是什么
【发布时间】:2011-02-15 17:43:10
【问题描述】:

我想将参数散列中的键与元素数组进行比较以进行匹配。

例如:

params          = {"key1", "key2", "key3"}
params_to_match = ["key2","key3"]

我可以这样做,但我确信有一种更优雅的方法可以达到相同的结果

params.each_key{|key|
  if params_to_match.include?(key.to_s)
    return
  end
}

【问题讨论】:

    标签: ruby algorithm hash iteration key


    【解决方案1】:

    不一定更高效,但在某种意义上也许更优雅

    return unless (params.keys & params_to_match).empty?
    

    比您的示例更有效的方法(在一般情况下,不一定是这样一个小玩具示例)是检查哈希是否包含键,因为在查找它们时查找它们的时间实际上是恒定的来自数组是 O(n)。所以,你的例子会变成这样:

    params_to_match.each { |p| return if params.has_key?(p) }
    

    【讨论】:

    • 在哈希中查找一个键是 O(n),而不是 O(1)。它是 1 的 big-theta
    【解决方案2】:

    使用&

    Set Intersection - 返回一个新数组,其中包含两个数组共有的元素,没有重复。

    [ 1, 1, 3, 5 ] & [ 1, 2, 3 ]   #=> [ 1, 3 ]
    
    params.keys & params_to_match  #=> ["key2", "key3"]
    

    【讨论】:

      【解决方案3】:

      我认为优雅和高效的最佳组合是

      return if params_to_match.any? { |p| params.has_key?(p) }
      

      如果你有 ActiveSupport,你可以这样做

      return if params.slice(*params_to_match).any?
      

      【讨论】:

        【解决方案4】:

        这是一个伪代码中的快速算法。

        assert keys, input are sorted
        pos = beginning of keys
        for i in input
          pos = keys.find(pos, i)  # find() starts search at position pos
          if not_found(pos) then return false
          ++pos
        return true
        

        这个算法,假设键和输入开始排序,在 O(n+m) 中执行,n 和 m 是键和输入的计数。我会留给你把它翻译成 Ruby,但要密切注意 find() 函数;它必须在上一次迭代中找到的位置开始搜索,而不是在键的开头。否则你只剩下 O(n^2+m), n 键数。

        【讨论】:

        • 仅供参考,您误解了问题,然后编辑了标题以匹配您认为的问题。另外,为什么哈希的键已经排序?使用哈希查找比这快得多。
        • 这取决于 ruby​​ 如何实现哈希映射,但如果它是一个搜索树,那么遍历它们将按排序顺序生成它们。如果它们未排序,则对它们进行排序:这会将性能更改为 O(n log n) + O(m),或 n + O(m) 的大θ,具体取决于排序算法。
        猜你喜欢
        • 1970-01-01
        • 2017-07-31
        • 2016-06-23
        • 1970-01-01
        • 2018-06-27
        • 2023-03-08
        • 1970-01-01
        • 2021-07-31
        • 1970-01-01
        相关资源
        最近更新 更多