Convert Named Matches in Matchdata to Hash

Convert named matches in MatchData to Hash

If you need a full Hash:

captures = Hash[ dimensions.names.zip( dimensions.captures ) ]
p captures
#=> {"width"=>"111", "height"=>"222", "depth"=>"333"}

If you just want to iterate over the name/value pairs:

dimensions.names.each do |name|
value = dimensions[name]
puts "%6s -> %s" % [ name, value ]
end
#=> width -> 111
#=> height -> 222
#=> depth -> 333

Alternatives:

dimensions.names.zip( dimensions.captures ).each do |name,value|
# ...
end

[ dimensions.names, dimensions.captures ].transpose.each do |name,value|
# ...
end

dimensions.names.each.with_index do |name,i|
value = dimensions.captures[i]
# ...
end

make hash consistent when some of its keys are symbols and others are not

You could transform the keys of datas to symbols:

Hash[ matchdatas.names.zip( matchdatas.captures ) ].transform_keys(&:to_sym)

Or to define your params hash with string keys:

params = { 'url' => 'http://myradiowebsite.com/thestation' }

How do you properly use 'match' to build a hash for every line in a file using ruby?

Things to consider:

IP_REGEX = '(?:\d{1,3}\.){3}\d{1,3}(?::\d+)?'
input = 'TCP OUTSIDE 4.2.2.2:443 INSIDE 10.17.21.44:63314, idle 0:00:44, bytes 11365, flags UIO'
input.scan(/(\w+)\s(#{ IP_REGEX })/)
# => [["OUTSIDE", "4.2.2.2:443"], ["INSIDE", "10.17.21.44:63314"]]

scan looks for the pattern given and returns an array of all matching hits. Because I'm using captures, they're returned as sub-arrays.

If you want the result to be a hash you can do:

input.scan(/(\w+)\s(#{ IP_REGEX })/).to_h # => {"OUTSIDE"=>"4.2.2.2:443", "INSIDE"=>"10.17.21.44:63314"}

or, if you're on an older Ruby that doesn't support to_h:

Hash[input.scan(/(\w+)\s(#{ IP_REGEX })/)] # => {"OUTSIDE"=>"4.2.2.2:443", "INSIDE"=>"10.17.21.44:63314"}

You could use a simpler scan pattern and allow parallel assignment help you grab the IPs in order:

src, dst = input.scan(/#{ IP_REGEX }/)

Then grab the other two fields however you want and assign them all to your hash:

foo = {
src: src,
dst: dst,
...
}

But, really, I'd take advantage of named captures:

matches = input.match(/(?<src>#{ IP_REGEX }) \w+ (?<dst>#{ IP_REGEX }), idle (?<idle>\S+), bytes (?<bytes>\d+), flags (?<flags>\S+)/)
# => #<MatchData
# "4.2.2.2:443 INSIDE 10.17.21.44:63314, idle 0:00:44, bytes 11365, flags UIO"
# src:"4.2.2.2:443"
# dst:"10.17.21.44:63314"
# idle:"0:00:44"
# bytes:"11365"
# flags:"UIO">
matches['src'] # => "4.2.2.2:443"
matches['dst'] # => "10.17.21.44:63314"
matches['idle'] # => "0:00:44"
matches['bytes'] # => "11365"
matches['flags'] # => "UIO"

At this point matches acts like a hash as far as allowing access to the individual elements.

If you don't like that it's a simple step to getting a real hash:

matches.names.zip(matches.captures).to_h
# => {"src"=>"4.2.2.2:443",
# "dst"=>"10.17.21.44:63314",
# "idle"=>"0:00:44",
# "bytes"=>"11365",
# "flags"=>"UIO"}

How can I get named parameters into a Hash?

def my_method(required_param, named_param_1: nil, named_param_2: nil)
named_params = method(__method__).parameters.each_with_object({}) do |p,h|
h[p[1]] = eval(p[1].to_s) if p[0] == :key
end
p named_params # {:named_param_1=>"hello", :named_param_2=>"world"}

# do something with the named params
end

my_method( 'foo', named_param_1: 'hello', named_param_2: 'world' )

Ruby Regex MatchData Object Captures Method Behaving Oddly

This is not a bug. It actually works properly. #captures only returns captured contents which mean the contents that are matched for groups within round brackets (). If you modify your regex to /(?!gemspec)gem(.*)/ (notice the (.*) part), reg.match("gem 'wirble', :group => :development").captures will return [" 'wirble', :group => :development"].

How to do named capture in ruby

You should use match with named captures, not scan

m = "555-333-7777".match(/(?<area>\d{3})-(?<city>\d{3})-(?<number>\d{4})/)
m # => #<MatchData "555-333-7777" area:"555" city:"333" number:"7777">
m[:area] # => "555"
m[:city] # => "333"

If you want an actual hash, you can use something like this:

m.names.zip(m.captures).to_h # => {"area"=>"555", "city"=>"333", "number"=>"7777"}

Or this (ruby 2.4 or later)

m.named_captures # => {"area"=>"555", "city"=>"333", "number"=>"7777"}

How can I use a regex match as a hash index in Ruby?

Try this

assessment.gsub(/#{farm.keys.join('|')}/, farm)

Ruby: Collect index from Array/String Matchdata

If you want to get each character's index as a hash, this would work:

b = %w(A B A A C C B D A D)

h = {}
b.each_with_index { |e, i|
h[e] ||= []
h[e] << i
}
h
#=> {"A"=>[0, 2, 3, 8], "B"=>[1, 6], "C"=>[4, 5], "D"=>[7, 9]}

Or as a "one-liner":

b.each_with_object({}).with_index { |(e, h), i| (h[e] ||= []) << i }
#=> {"A"=>[0, 2, 3, 8], "B"=>[1, 6], "C"=>[4, 5], "D"=>[7, 9]}


Related Topics



Leave a reply



Submit