Ruby: Easiest Way to Filter Hash Keys?

前端 未结 13 1191

I have a hash that looks something like this:

params = { :irrelevant => \"A String\",
           :choice1 => \"Oh look, another one\",
           :choi         


        
相关标签:
13条回答
  • 2020-11-30 18:38

    As for bonus question:

    1. If you have output from #select method like this (list of 2-element arrays):

      [[:choice1, "Oh look, another one"], [:choice2, "Even more strings"], [:choice3, "But wait"]]
      

      then simply take this result and execute:

      filtered_params.join("\t")
      # or if you want only values instead of pairs key-value
      filtered_params.map(&:last).join("\t")
      
    2. If you have output from #delete_if method like this (hash):

      {:choice1=>"Oh look, another one", :choice2=>"Even more strings", :choice3=>"But wait"}
      

      then:

      filtered_params.to_a.join("\t")
      # or
      filtered_params.values.join("\t")
      
    0 讨论(0)
  • 2020-11-30 18:40

    Edit to original answer: Even though this is answer (as of the time of this comment) is the selected answer, the original version of this answer is outdated.

    I'm adding an update here to help others avoid getting sidetracked by this answer like I did.

    As the other answer mentions, Ruby >= 2.5 added the Hash#slice method which was previously only available in Rails.

    Example:

    > { one: 1, two: 2, three: 3 }.slice(:one, :two)
    => {:one=>1, :two=>2}
    

    End of edit. What follows is the original answer which I guess will be useful if you're on Ruby < 2.5 without Rails, although I imagine that case is pretty uncommon at this point.


    If you're using Ruby, you can use the select method. You'll need to convert the key from a Symbol to a String to do the regexp match. This will give you a new Hash with just the choices in it.

    choices = params.select { |key, value| key.to_s.match(/^choice\d+/) }
    

    or you can use delete_if and modify the existing Hash e.g.

    params.delete_if { |key, value| !key.to_s.match(/choice\d+/) }
    

    or if it is just the keys and not the values you want then you can do:

    params.keys.select { |key| key.to_s.match(/^choice\d+/) }
    

    and this will give the just an Array of the keys e.g. [:choice1, :choice2, :choice3]

    0 讨论(0)
  • 2020-11-30 18:44

    With Hash::select:

    params = params.select { |key, value| /^choice\d+$/.match(key.to_s) }
    
    0 讨论(0)
  • 2020-11-30 18:44

    I had a similar problem, in my case the solution was a one liner which works even if the keys aren't symbols, but you need to have the criteria keys in an array

    criteria_array = [:choice1, :choice2]
    
    params.select { |k,v| criteria_array.include?(k) } #=> { :choice1 => "Oh look another one",
                                                             :choice2 => "Even more strings" }
    

    Another example

    criteria_array = [1, 2, 3]
    
    params = { 1 => "A String",
               17 => "Oh look, another one",
               25 => "Even more strings",
               49 => "But wait",
               105 => "The last string" }
    
    params.select { |k,v| criteria_array.include?(k) } #=> { 1 => "A String"}
    
    0 讨论(0)
  • 2020-11-30 18:45

    If you want the remaining hash:

    params.delete_if {|k, v| ! k.match(/choice[0-9]+/)}
    

    or if you just want the keys:

    params.keys.delete_if {|k| ! k.match(/choice[0-9]+/)}
    
    0 讨论(0)
  • 2020-11-30 18:51
    params.select{ |k,v| k =~ /choice\d/ }.map{ |k,v| v}.join("\t")
    
    0 讨论(0)
提交回复
热议问题