codereading / rack

a modular Ruby webserver interface
http://rack.rubyforge.org/
Other
18 stars 2 forks source link

Array to Hash snippet #3

Open birula opened 12 years ago

birula commented 12 years ago

I was looking around the code and found this piece of code that turns an array into a Hash. The basic idea is to flatten an array to create a list of key, value and then pass it into a Hash[].

https://github.com/codereading/rack/blob/rack-1.4/lib/rack/request.rb#L57

ary = [ [:foo, "bar"], [:fii, "baz"] ].flatten    #=> [ :foo, "bar", :fii, "baz"]
Hash[ary]                                         #=> {"foo"=> "bar", "fii"=> "baz"}

Hash[*content_type.split(/\s*[;,]\s*/)[1..-1].
  collect { |s| s.split('=', 2) }.
  map { |k,v| [k.downcase, v] }.flatten]

This may be not a big thing but I brought it on because I've used it a couple of times.

Monomachus commented 12 years ago

what does this other line?

Hash[_contenttype.split(/\s[;,]\s*/)[1..-1]. collect { |s| s.split('=', 2) }. map { |k,v| [k.downcase, v] }.flatten]

samnang commented 12 years ago

@birula I think you are missing splat operator Hash[ary] in your example, so what it should be is Hash[*ary].

Another interesting collect or map is just an alias of another. Why don't they keep using one consistant instead of mixing in using all together?

birula commented 12 years ago

@samnang You're right i forgot * before the array, just don't now why is it used.

Doesn't it sound like you're trying to map a [key, value] pairs and collect anything else? It looks silly but i use those methods that way.

birula commented 12 years ago

@Monomachus this line convert the header information from a request "text/html; charset=utf-8" into an array [["charset", "utf-8"]] and then to a hash { "charset" => "utf-8" }

If you look closely it excludes the "text/html" from the string in the first step.

birula commented 12 years ago

There's another interesting thing in this code, after the first split it gets the last element with [1..-1] why not just use the .last method ?

content_type.split(/\s*[;,]\s*/)[1..-1]
content_type.split(/\s*[;,]\s*/).last
tomykaira commented 12 years ago

@birula, try more than one media parameters.

last takes only the last element, whereas [1..-1] takes other than the first element. Plus, the former returns an object in array, the latter returns an array.

birula commented 12 years ago

@tomykaira you're completely right using last in this case is wrong.

razum2um commented 12 years ago

would it be more efficiently? (or not?) i.e. would [1..-1] allocate one more array?

content_type.split(/\s*[;,]\s*/).tap(&:shift)