From: Brian Candler Date: 2003-07-22T01:43:46+09:00 Subject: Re: Proposal: Array#to_h, to simplify hash generation On Tue, Jul 22, 2003 at 01:23:07AM +0900, Simon Strandgaard wrote: > May I suggest a Enum#build routine, working like this pseudo code > > [1, 2, 3].build(Hash) { |i| i, f(i) } > #=> {1=>"f(1)", 2=>"f(3)", 3=>"f(3)"} > > [1, 2, 3].build(String) { |i| i.class } > #=> "FixnumFixnumFixnum" > > [1, 2, 3].build(Array) { |i| Regex.new(i.to_s) } > #=> [/1/, /2/, /3/] > > Is this madness, appending elements this way ? > Especialy will this work for hash ? Hmm, interesting idea: a way to delegate collection to different classes without having to clutter up Enumerable with collect_hash, collect_string etc. If a class implements a standard "add element" method, perhaps <<, then how about this: class Array # repeat for module Enumerable as well def collect(dest=Array,*args) res = dest.new(*args) each do |item| res << yield(item) end res end end class Hash def <<(kvpair) self[kvpair[0]] = kvpair[1] end end a = [["one","two"],["three","four"],["five","six"]] p a.collect {|e| e[0]} #>> ["one", "three", "five"] p a.collect(String,"") {|e| e[1]} #>> "twofoursix" p a.collect(Hash) {|e| e} #>> {"five"=>"six", "three"=>"four", "one"=>"two"} The bit I don't like is Hash#<< taking an array of two elements, rather than having two arguments, but I guess that's what you get from having a method rather than a proc. 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. Your examples work, with minor modification: def f(i) i*i; end p [1, 2, 3].collect(Hash) { |i| [i, f(i)] } # {1=>1, 2=>4, 3=>9} p [1, 2, 3].collect(String,"") { |i| i.class.to_s } # "FixnumFixnumFixnum" p [1, 2, 3].collect(Array) { |i| Regexp.new(i.to_s) } # [/1/, /2/, /3/] Cheers, Brian.