Home > Software design >  One line code for array of content to convert dictionary of values in ruby
One line code for array of content to convert dictionary of values in ruby

Time:05-24

data =  [ "         64               40               64              41   144      144\r\n", "         68               40               64              41   144      144\r\n", "         72               41               64              41   144      144\r\n", "         76               41               64              41   144      144\r\n", "        128               41               64              41   144      144\r\n", "        132               41               64              42   144      144\r\n", "        136               41               64              42   144      144\r\n", "        140               41               64              42   144      144\r\n"]
re = /\s (\d )\s (\d )/
dlm = []
data.each do |arr|
    val = arr.scan(re).flatten.reject(&:empty?).map(&:to_i)
    unless val.empty?
      d = {}
      d["x"] = val[0]
      d["y"] = val[1]
      d["z"] = val[2]
      d["m"] = val[3]
      d["n"] = val[4]
      d["o"] = val[5]
      dlm.append(d)
     end
end

I need the above code in one line with ruby. Can someone please help with this?

CodePudding user response:

You can write that as follows.

keys = ["x", "y", "m", "n", "o"]
data.map { |s| keys.zip(s.scan(/\d /).map(&:to_i)).to_h }
  #=> [{"x"=>64,  "y"=>40, "m"=>64, "n"=>41, "o"=>144},
  #    {"x"=>68,  "y"=>40, "m"=>64, "n"=>41, "o"=>144},
  #    {"x"=>72,  "y"=>41, "m"=>64, "n"=>41, "o"=>144},
  #    {"x"=>76,  "y"=>41, "m"=>64, "n"=>41, "o"=>144},
  #    {"x"=>128, "y"=>41, "m"=>64, "n"=>41, "o"=>144},
  #    {"x"=>132, "y"=>41, "m"=>64, "n"=>42, "o"=>144},
  #    {"x"=>136, "y"=>41, "m"=>64, "n"=>42, "o"=>144},
  #    {"x"=>140, "y"=>41, "m"=>64, "n"=>42, "o"=>144}]

You could of course remove the line defining keys by substituting out the variable keys in the second line.

Here are the steps for the first two elements of data that are passed to the block by map:

s = data[0]
  #=> "      64            40            64           41   144   144\r\n"
a = s.scan(/\d /)
  #=> ["64", "40", "64", "41", "144", "144"]
b = a.map(&:to_i)
  #=> [64, 40, 64, 41, 144, 144]
c = keys.zip(b)
  #=> [["x", 64], ["y", 40], ["m", 64], ["n", 41], ["o", 144]]
c.to_h
  #=> {"x"=>64, "y"=>40, "m"=>64, "n"=>41, "o"=>144}
s = data[1]
  #=> "      68            40            64           41   144   144\r\n"
a = s.scan(/\d /)
  #=> ["68", "40", "64", "41", "144", "144"]
b = a.map(&:to_i)
  #=> [68, 40, 64, 41, 144, 144]
c = keys.zip(b)
  #=> [["x", 68], ["y", 40], ["m", 64], ["n", 41], ["o", 144]]
c.to_h
  #=> {"x"=>68, "y"=>40, "m"=>64, "n"=>41, "o"=>144}

CodePudding user response:

Ruby does not require line breaks. They are always optional and can always be replaced with either whitespace, an expression separator, or a keyword.

Which means you can always write any Ruby program in one line by simply removing the line breaks:

data =  [ "         64               40               64              41   144      144\r\n", "         68               40               64              41   144      144\r\n", "         72               41               64              41   144      144\r\n", "         76               41               64              41   144      144\r\n", "        128               41               64              41   144      144\r\n", "        132               41               64              42   144      144\r\n", "        136               41               64              42   144      144\r\n", "        140               41               64              42   144      144\r\n"]; re = /\s (\d )\s (\d )/; dlm = []; data.each do |arr| val = arr.scan(re).flatten.reject(&:empty?).map(&:to_i); unless val.empty? then d = {}; d["x"] = val[0]; d["y"] = val[1]; d["z"] = val[2]; d["m"] = val[3]; d["n"] = val[4]; d["o"] = val[5]; dlm.append(d) end end

There you go. Your code in one line.

  •  Tags:  
  • ruby
  • Related