Proposal: Array#to_h, to simplify hash generation

Ask a Question related to Ruby, Design and Development.

  1. #21

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tuesday, July 22, 2003, 12:43:19 AM, ts wrote:
    >>>>>> "G" == Gavin Sinclair <gsinclair@soyabean.com.au> writes:
    G>> tested code vanishes before everyone's eyes. I was surprised to
    G>> discover today that code (1) below works, but not code (2).

    G>> (1) def foo; 2,4; end
    G>> (2) def foo; return 2,4; end
    > Well, you want to say say (2) work but not (1), no ?
    Thanks. I really do get things wrong far too much.

    Gavin


    Gavin Sinclair Guest

  2. Similar Questions and Discussions

    1. hash of hash of array slices
      This works Foreach ( @{$hash{$key1}{$key2}} ) This does note Foreach ( @{($hash{$key1}{$key2})} ) This gives me this error .... Can't...
    2. [PHP-DEV] EOT (was [PHP-DEV] Proposal: Array syntax)
      On Thu, 6 Nov 2003, Andi Gutmans wrote: If there was anything constructive in that long thread of "I like it" -- "no, I don't!" I might agree...
    3. [PHP-DEV] EOT (was [PHP-DEV] Proposal: Array syntax)
      Sascha, I don't think it's a private matter. Feel free to delete the emails with this subject when they come in. Andi At 01:30 PM 11/6/2003...
    4. Re[2]: [PHP-DEV] Proposal: Array syntax
      Hi The problem i see when using array() (or list()) is that it nearly looks like it is a function, but it isn't. Using instead would clearly...
    5. hash generation question
      Stephan wrote: How's this related to the modules list? Anyhow, what about this: my $hashref = \%hash; $hashref = $hashref->{$_} foreach...
  3. #22

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, Jul 22, 2003 at 01:02:53AM +0900, Jason Creighton wrote:
    > I would almost prefer [1,2,3,4].to_h => {1=>2, 3=>4}
    You have that already:

    irb(main):001:0> Hash[1,2,3,4]
    => {1=>2, 3=>4}

    Cheers,

    Brian.

    Brian Candler Guest

  4. #23

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, 22 Jul 2003 01:43:46 +0900
    Brian Candler <B.Candler@pobox.com> wrote:
    > A minor quibble comes out of this: why doesn't String.new with no arguments
    > just return an empty string? In 1.6.8 it gives an ArgumentError exception.
    ~$ ruby -v
    ruby 1.8.0 (2003-06-23) [i686-linux]
    ~$ irb
    >> String.new
    => ""

    Jason Creighton

    Jason Creighton Guest

  5. #24

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, Jul 22, 2003 at 01:43:46AM +0900, Brian Candler wrote:
    > The bit I don't like is Hash#<< taking an array of two elements, rather than
    > having two arguments
    I forgot about using Method#arity. New version attached... Brian.

    class Array # ditto for Enumerable
    def collect(dest=Array,*args)
    res = dest.new(*args)
    if res.method(:<<).arity == 1
    each do |item|
    res << yield(item)
    end
    else
    each do |item|
    res.send(:<<, *yield(item))
    end
    end
    res
    end
    end

    class Hash
    def <<(key,val)
    self[key] = val
    end
    end

    a = [["one","two"],["three","four"],["five","six"]]

    p a.collect {|e| e[0]}
    p a.collect(String,"") {|e| e[1]}
    p a.collect(Hash) {|e| e}
    p a.collect(Hash) {|k,v| [v,k]} # like Hash#invert

    def f(i) i*i; end

    p [1, 2, 3].collect(Hash) { |i| [i, f(i)] }
    p [1, 2, 3].collect(String,"") { |i| i.class.to_s }
    p [1, 2, 3].collect(Array) { |i| Regexp.new(i.to_s) }

    Brian Candler Guest

  6. #25

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, 22 Jul 2003 02:57:40 +0900, Brian Candler wrote:
    > On Tue, Jul 22, 2003 at 01:43:46AM +0900, Brian Candler wrote:
    >> The bit I don't like is Hash#<< taking an array of two elements, rather than
    >> having two arguments
    >
    > I forgot about using Method#arity. New version attached... Brian.
    >
    > class Array # ditto for Enumerable
    > def collect(dest=Array,*args)
    > res = dest.new(*args)
    Maybe its better to do the #new outside collect ?

    Like this:
    [1, 2, 3].collect(String.new("Test: ")) { |i| i.class }
    # "Test: FixnumFixnumFixnum"

    res = Hash.new
    def f(v) v*v; end
    [1, 2].map(res) {|i| [i, f(i)] }
    [3, 4].map(res) {|i| [i, f(i-2)] }
    p res # print the accumulated result
    # {1=>1, 2=>4, 3=>1, 4=>4}


    Accumulating is good :-)

    --
    Simon Strandgaard
    Simon Strandgaard Guest

  7. #26

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, Jul 22, 2003 at 02:04:08AM +0900, Jason Creighton wrote:
    > > A minor quibble comes out of this: why doesn't String.new with no arguments
    > > just return an empty string? In 1.6.8 it gives an ArgumentError exception.
    >
    > ~$ ruby -v
    > ruby 1.8.0 (2003-06-23) [i686-linux]
    > ~$ irb
    > >> String.new
    > => ""
    Thanks. Must get 1.8pre installed somewhere.

    Another idea for code just posted: change two lines as follows,

    def collect(res=Array,*args)
    res = res.new(*args) if res.is_a? Class

    Then collect could append to an existing object as well:

    [1, 2, 3].collect("fred") { |x| x.to_s} #>> "fred123"

    h = {"one"=>"two"}
    [["three","four"]].collect(h) {|x| x} #>> {"one"=>"two","three"=>"four"}

    The dangerous thing is that you are modifying an existing object, whereas
    collect normally generates a new instance of something.

    But this pattern covers a whole lot of existing cases: e.g.

    h1.update(h2)

    is just a short form for

    h2.collect(h1) {|x| x}

    Perhaps "collect_into" would be a better name for this new method?

    Cheers,

    Brian.

    Brian Candler Guest

  8. #27

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, 22 Jul 2003 06:00:53 +0900, Brian Candler wrote:
    > On Tue, Jul 22, 2003 at 02:24:35AM +0900, Simon Strandgaard wrote:
    >> On Tue, 22 Jul 2003 02:57:40 +0900, Brian Candler wrote:
    >>
    >> > On Tue, Jul 22, 2003 at 01:43:46AM +0900, Brian Candler wrote:
    >> >> The bit I don't like is Hash#<< taking an array of two elements, rather than
    >> >> having two arguments
    >> >
    >> > I forgot about using Method#arity. New version attached... Brian.
    >> >
    >> > class Array # ditto for Enumerable
    >> > def collect(dest=Array,*args)
    >> > res = dest.new(*args)
    >>
    >> Maybe its better to do the #new outside collect ?
    >
    > Yes, I worked that out in parallel with you :-) Thinking while walking home,
    > the pattern
    :-)

    > Since not all objects necessarily have a '<<' method then maybe it's worth
    > having that as a parameter as well. The attached code lets you do that, or
    > guesses at a suitable method if one isn't provided.
    Good idea to test for different append methods


    [snip code]


    #collect_into / #map_into is nice.
    How about abbreviating the name, so its just: #into


    p [1, "2", 3].into({}) { |i| [i.class, i] }
    # {"Fixnum"=>[1, 3], "String"=>["2"]}


    Important: Hash#append should not overwrite earlier entries.

    --
    Simon Strandgaard
    Simon Strandgaard Guest

  9. #28

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Tue, Jul 22, 2003 at 05:46:35AM +0900, Simon Strandgaard wrote:
    > Important: Hash#append should not overwrite earlier entries.
    Hmm. What should it do then? Raise an exception? h1.update(h2) will
    overwrite corresponding keys in h1, so there is a precedent for collect_into
    working in that way.

    I would rule out, say, automatically promoting a value into an array. It's
    too application-specific. If your application does in fact hold a hash of
    arrays, then I think you'd code your append method accordingly; in other
    cases, the structure may be different (a hash of hashes, say), in which case
    the append method is different.

    Cheers,

    Brian.

    Brian Candler Guest

  10. #29

    Default Re: Proposal: Array#to_h, to simplify hash generation

    On Sat, 19 Jul 2003 23:22:20 +0900
    Gavin Sinclair <gsinclair@soyabean.com.au> wrote:
    > Hi -talk,
    >
    > Ruby has wonderful support for chewing and spitting arrays. For
    > instance, it's easy to produce an array from any Enumerable using
    > #map. With hashes, however, it's a bit more cumbersome.
    >
    > For example, the following method is typical of my code:
    >
    > # return { filename -> size }
    > def get_local_gz_files
    > files = {}
    > Dir["*.gz"].each do |filename|
    > files[filename] = File.stat(filename).size
    > end
    > files
    > end
    One option, in this case, is to hijack the Hash#new block form:

    files = Hash.new { |hash, key| hash[key] = File.stat(key).size }

    files is now a "magic" hash that will stat any file that that's used as a key.
    If you're not just doing random access, you could fill it like so:

    Dir["*.gz"].each { |f| files[f] }

    The block will be called to return a value instead of nil when a key is missing:
    We assign to the hash to save that value as well. You can do all *sorts* of
    weird stuff using this feature:
    >> e = Hash.new { |h, k| eval(k) }
    => {}
    >> e["Time.now"]
    => Tue Jul 22 13:32:56 MDT 2003
    <wait a couple seconds>
    >> e["Time.now"]
    => Tue Jul 22 13:33:03 MDT 2003
    >> e = Hash.new { |h, k| h[k] = eval(k) }
    => {}
    >> e["Time.now"]
    => Tue Jul 22 13:35:09 MDT 2003
    <wait a couple seconds>
    >> e["Time.now"]
    => Tue Jul 22 13:35:09 MDT 2003

    Jason Creighton
    Jason Creighton Guest

Posting Permissions

  • You may not post new threads
  • You may post replies
  • You may not post attachments
  • You may not edit your posts

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139