All possible combinations from a hash of arrays in Ruby

后端 未结 4 2003
忘掉有多难
忘掉有多难 2021-02-05 08:01

What I have:

Let\'s say I have a hash like this, with various values belonging to one parameter.

a = {}
a[:bitrate] = [\"100\", \"500\", \"1000\"]
a[:f         


        
相关标签:
4条回答
  • 2021-02-05 08:20

    Please try OCG options combination generator.

    require "ocg"
    
    generator = OCG.new(
      :bitrate => %w[100 500 1000],
      :fps => %w[15 30],
      :qp => %w[20 30]
    )
    
    puts generator.next until generator.finished?
    

    Generator includes much more functionality that will help you to deal with other options.

    0 讨论(0)
  • 2021-02-05 08:29
    a = {}
    a[:bitrate] = ["100", "500", "1000"]
    a[:fps] = ["15", "30"]
    a[:qp] = ["20", "30"]
    
    def product_hash(hsh)
      attrs   = hsh.values
      keys    = hsh.keys
      product = attrs[0].product(*attrs[1..-1])
      product.map{ |p| Hash[keys.zip p] }
    end
    
    product_hash(a)
    

    you'll get

    [{:bitrate=>"100", :fps=>"15", :qp=>"20"},
     {:bitrate=>"100", :fps=>"15", :qp=>"30"},
     {:bitrate=>"100", :fps=>"30", :qp=>"20"},
     {:bitrate=>"100", :fps=>"30", :qp=>"30"},
     {:bitrate=>"500", :fps=>"15", :qp=>"20"},
     {:bitrate=>"500", :fps=>"15", :qp=>"30"},
     {:bitrate=>"500", :fps=>"30", :qp=>"20"},
     {:bitrate=>"500", :fps=>"30", :qp=>"30"},
     {:bitrate=>"1000", :fps=>"15", :qp=>"20"},
     {:bitrate=>"1000", :fps=>"15", :qp=>"30"},
     {:bitrate=>"1000", :fps=>"30", :qp=>"20"},
     {:bitrate=>"1000", :fps=>"30", :qp=>"30"}]
    

    You can also add new key to your hash.

    a = {}
    a[:bitrate] = ["100", "500", "1000"]
    a[:fps] = ["15", "30"]
    a[:qp] = ["20", "30"]
    a[:bw] = [true, false]
    
    product_hash(a)
    
    #=>
    [{:bitrate=>"100", :fps=>"15", :qp=>"20", :bw=>true},
     {:bitrate=>"100", :fps=>"15", :qp=>"20", :bw=>false},
     {:bitrate=>"100", :fps=>"15", :qp=>"30", :bw=>true},
     {:bitrate=>"100", :fps=>"15", :qp=>"30", :bw=>false},
     {:bitrate=>"100", :fps=>"30", :qp=>"20", :bw=>true},
     {:bitrate=>"100", :fps=>"30", :qp=>"20", :bw=>false},
     {:bitrate=>"100", :fps=>"30", :qp=>"30", :bw=>true},
     {:bitrate=>"100", :fps=>"30", :qp=>"30", :bw=>false},
     {:bitrate=>"500", :fps=>"15", :qp=>"20", :bw=>true},
     {:bitrate=>"500", :fps=>"15", :qp=>"20", :bw=>false},
     {:bitrate=>"500", :fps=>"15", :qp=>"30", :bw=>true},
     {:bitrate=>"500", :fps=>"15", :qp=>"30", :bw=>false},
     {:bitrate=>"500", :fps=>"30", :qp=>"20", :bw=>true},
     {:bitrate=>"500", :fps=>"30", :qp=>"20", :bw=>false},
     {:bitrate=>"500", :fps=>"30", :qp=>"30", :bw=>true},
     {:bitrate=>"500", :fps=>"30", :qp=>"30", :bw=>false},
     {:bitrate=>"1000", :fps=>"15", :qp=>"20", :bw=>true},
     {:bitrate=>"1000", :fps=>"15", :qp=>"20", :bw=>false},
     {:bitrate=>"1000", :fps=>"15", :qp=>"30", :bw=>true},
     {:bitrate=>"1000", :fps=>"15", :qp=>"30", :bw=>false},
     {:bitrate=>"1000", :fps=>"30", :qp=>"20", :bw=>true},
     {:bitrate=>"1000", :fps=>"30", :qp=>"20", :bw=>false},
     {:bitrate=>"1000", :fps=>"30", :qp=>"30", :bw=>true},
     {:bitrate=>"1000", :fps=>"30", :qp=>"30", :bw=>false}]
    
    0 讨论(0)
  • 2021-02-05 08:30

    Just FYI I took fl00r's approach and monkey-patched it. I like it a bit better.

    class Hash
      def product
        product = values[0].product(*values[1..-1])
        product.map{|p| Hash[keys.zip p]}
      end
    end
    
    0 讨论(0)
  • 2021-02-05 08:31

    I believe fl00r's answer is almost perfect but has a drawback. It assumes that hsh.values and hsh.keys will have a matching order, which as far as I know, is not warrantied. So you will probably need an extra step to ensure that. Maybe something like:

    def product_hash(hsh)
      keys  = hsh.keys
      attrs = keys.map { |key| hsh[key] }
      product = attrs[0].product(*attrs[1..-1])
      product.map{ |p| Hash[keys.zip p] }
    end
    

    But fl00r can correct me if I'm wrong.

    0 讨论(0)
提交回复
热议问题