Dorren
January 24, 2007, 11:45pm
1
doing access control on rails controller,
------ I have this input --------------
hash = {“index” => “list”,
[“edit”, “update”] => “manage_one”,
[“new”, “create”, “destroy”] => “manage_all”}
------- I want this output ----------
{“index”=>“list”,
“edit”=>“manage_one”,
“update”=>“manage_one”,
“new”=>“manage_all”,
“create”=>“manage_all”,
“destroy”=>“manage_all”
}
------ I have this code ------------
hash = Hash[*hash.to_a.collect{|x|
Array === x[0] ? x[0].zip([x[1]]*x[0].size) : x
}.flatten]
----- I want shorter code ------
thanks.
Dorren
January 25, 2007, 12:06am
2
a little clearer than previous one.
hash = Hash[hash.inject([]){|arr, (k, v)|
arr += Array === k ? k.zip([v] k.size)
: [k, v]
}.flatten]
Dorren
January 25, 2007, 12:15am
3
Dorren wrote:
“update”=>“manage_one”,
----- I want shorter code ------
What about this:
h = {}
for k,v in hash
[k].flatten.each {|l| h[l] = v}
end
hash = h
=> {“new”=>“manage_all”, “edit”=>“manage_one”,
“destroy”=>“manage_all”, “create”=>“manage_all”, “index”=>“list”,
“update”=>“manage_one”}
Cheers,
Vincent
Dorren
January 25, 2007, 12:22am
4
Vincent F. wrote:
h = {}
for k,v in hash
[k].flatten.each {|l| h[l] = v}
end
hash = h
Actually, I’ve got shorter ;-):
h = {}
for k,v in hash
[*k].each {|l| h[l] = v}
end
hash = h
Vince
Dorren
January 25, 2007, 12:31am
5
better, thank tou.
On Jan 24, 6:14 pm, Vincent F. [email protected]
Dorren
January 25, 2007, 2:55am
6
On Jan 24, 5:01 pm, “Dorren” [email protected] wrote:
a little clearer than previous one.
hash = Hash[hash.inject([]){|arr, (k, v)|
arr += Array === k ? k.zip([v] k.size)
: [k, v]
}.flatten]
Hash[ *hash.map{|k,v| k=[*k]; k.zip([v]*k.size) }.flatten ]
Dorren
January 25, 2007, 3:30am
7
Vincent F. [email protected] writes:
Actually, I’ve got shorter ;-):
h = {}
for k,v in hash
[*k].each {|l| h[l] = v}
end
hash = h
Well, if we’re golfing:
h={};hash.map{|k,v|[*k].map{|t|h[t]=v}};h
Dorren
January 25, 2007, 11:06am
8
On 25.01.2007 03:29, Daniel M. wrote:
Well, if we’re golfing:
h={};hash.map{|k,v|[*k].map{|t|h[t]=v}};h
Not really shorter but I though there should be at least one solution
with #inject:
hash.inject({}){|h,(k,v)| k.to_a.each {|x| h[x]=v};h}
=> {“new”=>“manage_all”, “edit”=>“manage_one”, “destroy”=>“manage_all”,
“create”=>“manage_all”, “index”=>“list”, “update”=>“manage_one”}
hash.inject({}){|h,(k,v)| k.each {|x| h[x]=v} rescue h[k]=v;h}
=> {“new”=>“manage_all”, “edit”=>“manage_one”, “destroy”=>“manage_all”,
“create”=>“manage_all”, “index”=>“list”, “update”=>“manage_one”}
robert
Dorren
January 25, 2007, 11:28am
9
On Jan 24, 2007, at 15:20, Vincent F. wrote:
for k,v in hash
[*k].each {|l| h[l] = v}
end
hash = h
but fastest (I assume all entries worked correctly):
$ ruby bm.rb
Rehearsal --------------------------------------------------------
original 10.440000 0.010000 10.450000 ( 10.492738)
original clean 11.480000 0.040000 11.520000 ( 11.632237)
vince 5.210000 0.010000 5.220000 ( 5.264394)
william 12.760000 0.020000 12.780000 ( 12.814230)
daniel 6.900000 0.010000 6.910000 ( 6.924297)
robert inject 6.560000 0.000000 6.560000 ( 6.588160)
robert inject rescue 6.080000 0.010000 6.090000 ( 6.094140)
---------------------------------------------- total: 59.530000sec
user system total real
original 10.450000 0.010000 10.460000 ( 10.467971)
original clean 11.490000 0.030000 11.520000 ( 11.600672)
vince 5.210000 0.000000 5.210000 ( 5.219863)
william 12.820000 0.010000 12.830000 ( 12.839722)
daniel 6.930000 0.010000 6.940000 ( 6.945329)
robert inject 6.580000 0.010000 6.590000 ( 6.591095)
robert inject rescue 6.080000 0.000000 6.080000 ( 6.117226)
Dorren
January 25, 2007, 12:49pm
10
There’s a glitch, which is not yet mentioned…
Consider this old hash: {[“A”, “B”]=>“C”, [“B”, “A”]=>“D”}
What’s the value of new_hash[“A”]? Is it “C”, or is it “D”?
That depends on the order on which you build the new hash.
Which depends on the order in which you walk through the old
hash. Which isn’t deterministic, AFAIK. Maybe it is
determinstic if you know in which order the old hash was built.
But, given a hash, you simply don’t know the order in which
you walk through it, so you don’t know the order in which the
new hash will be built, so you don’t know what the result is
going to be. Cool…
Adding a sort to the algorithm fixes this.
gegroet,
Erik V. - http://www.erikveen.dds.nl/
hash.collect do |k,v|
[[k].flatten, v]
end.sort.inject({}) do |h,(ks,v)|
ks.each do |k|
h[k] = v
end
h
end