can it be shorter?

Discussion in 'Ruby' started by Dorren, Jan 24, 2007.

  1. Dorren

    Dorren Guest

    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, Jan 24, 2007
    #1
    1. Advertising

  2. Dorren

    Dorren Guest

    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, Jan 24, 2007
    #2
    1. Advertising

  3. Dorren wrote:
    > 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 ------


    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

    --
    Vincent Fourmond, PhD student (not for long anymore)
    http://vincent.fourmond.neuf.fr/
     
    Vincent Fourmond, Jan 24, 2007
    #3
  4. Vincent Fourmond 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

    --
    Vincent Fourmond, PhD student (not for long anymore)
    http://vincent.fourmond.neuf.fr/
     
    Vincent Fourmond, Jan 24, 2007
    #4
  5. Dorren

    Dorren Guest

    better, thank tou.

    On Jan 24, 6:14 pm, Vincent Fourmond <>
    wrote:
    > Dorren wrote:
    > > 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 ------ 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
    >
    > --
    > Vincent Fourmond, PhD student (not for long anymore)http://vincent.fourmond.neuf.fr/
     
    Dorren, Jan 24, 2007
    #5
  6. On Jan 24, 5:01 pm, "Dorren" <> 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 ]
     
    William James, Jan 25, 2007
    #6
  7. Vincent Fourmond <> 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

    --
    s=%q( Daniel Martin --
    puts "s=%q(#{s})",s.map{|i|i}[1] )
    puts "s=%q(#{s})",s.map{|i|i}[1]
     
    Daniel Martin, Jan 25, 2007
    #7
  8. On 25.01.2007 03:29, Daniel Martin wrote:
    > Vincent Fourmond <> 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


    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
     
    Robert Klemme, Jan 25, 2007
    #8
  9. Dorren

    Eric Hodel Guest

    --Apple-Mail-2-287622042
    Content-Transfer-Encoding: 7bit
    Content-Type: text/plain;
    charset=US-ASCII;
    format=flowed

    On Jan 24, 2007, at 15:20, Vincent Fourmond wrote:
    > Vincent Fourmond 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


    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)


    --Apple-Mail-2-287622042
    Content-Transfer-Encoding: 7bit
    Content-Type: text/x-ruby-script;
    x-unix-mode=0644;
    name=bm.rb
    Content-Disposition: attachment;
    filename=bm.rb

    require 'benchmark'

    N = 500_000

    hash = {
    "index" => "list",
    ["edit", "update"] => "manage_one",
    ["new", "create", "destroy"] => "manage_all"
    }

    Benchmark.bmbm do |bm|

    bm.report 'original' do
    N.times do
    Hash[*hash.to_a.collect{|x|
    Array === x[0] ? x[0].zip([x[1]]*x[0].size) : x
    }.flatten]
    end
    end

    bm.report 'original clean' do
    N.times do
    Hash[*hash.inject([]){|arr, (k, v)|
    arr += Array === k ? k.zip([v]* k.size) : [k, v]
    }.flatten]
    end
    end

    bm.report 'vince' do
    N.times do
    h = {}
    for k,v in hash
    [*k].each {|l| h[l] = v}
    end
    end
    end

    bm.report 'william' do
    N.times do
    Hash[ *hash.map{|k,v| k=[*k]; k.zip([v]*k.size) }.flatten ]
    end
    end

    bm.report 'daniel' do
    N.times do
    h={};hash.map{|k,v|[*k].map{|t|h[t]=v}}
    end
    end

    bm.report 'robert inject' do
    N.times do
    hash.inject({}){|h,(k,v)| k.to_a.each {|x| h[x]=v};h}
    end
    end

    bm.report 'robert inject rescue' do
    N.times do
    hash.inject({}){|h,(k,v)| k.each {|x| h[x]=v} rescue h[k]=v;h}
    end
    end

    end


    --Apple-Mail-2-287622042
    Content-Transfer-Encoding: 7bit
    Content-Type: text/plain;
    charset=US-ASCII;
    format=flowed


    --
    Eric Hodel - - http://blog.segment7.net

    I LIT YOUR GEM ON FIRE!


    --Apple-Mail-2-287622042--
     
    Eric Hodel, Jan 25, 2007
    #9
  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

    ----------------------------------------------------------------
     
    Erik Veenstra, Jan 25, 2007
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. chenyu
    Replies:
    1
    Views:
    289
    Bob Gailer
    Nov 12, 2003
  2. Lowell Kirsh

    how can I make this script shorter?

    Lowell Kirsh, Feb 22, 2005, in forum: Python
    Replies:
    7
    Views:
    290
    Christos TZOTZIOY Georgiou
    Feb 25, 2005
  3. trvlDev
    Replies:
    3
    Views:
    273
    trvlDev
    Apr 6, 2007
  4. kj

    Re: can it be shorter?

    kj, Jun 6, 2009, in forum: Python
    Replies:
    5
    Views:
    331
  5. Aaron Brady

    Re: can it be shorter?

    Aaron Brady, Jun 7, 2009, in forum: Python
    Replies:
    7
    Views:
    348
    Carlos Valiente
    Jun 11, 2009
Loading...

Share This Page