From: dblack@... Date: 2002-11-17T02:18:51+09:00 Subject: Re: ruby-dev summary 18613-18710 Hi -- On Sat, 16 Nov 2002, Florian Frank wrote: > On 2002-11-16 06:07:50 +0900, dblack@candle.superlink.net wrote: > > > module Enumerable > > > > > > def zip(&block) > > > block ||= lambda { |*tuple| tuple } > > > size = nil > > > map { |x| x.size }.each do |s| > > > size ||= s > > > s == size or raise "zip with unequal length lists" > > > end > > > result = [] > > > i = 0 > > > catch(:stop) do > > > > (Don't you like regular Ruby iterators? :-) > > I like them, but I can't use an iterator here. I needed to get the i-th > element of every object l in the enumerable self. It would be better to > use while instead. If you want the i-th element of each object, just iterate through the objects and grab the i-th element :-) In fact you can save yourself a lot of typing. Here's a rewrite: module Enumerable def zip(&block) block ||= lambda { |*tuple| tuple } if map {|e| e.size}.uniq.size > 1 raise "zip with unequal length lists" else (0...size).map {|i| block.call(*map {|l| l[i]})} end end end Mind you, I'm not currently a fan of the exception for unequal lengths, and I actually prefer this: ary.zip(ary2, ary3) to this: [ary1, ary2, ary3].zip but anyway, you can definitely get things more concise, for your version, by letting Ruby doing the work for you. > > What would the effect be of calling #zip on a non-Array Enumerable, > > for example a String? > > > > "abcde".zip # => ? > > "abcde".zip > ==>[[97], [98], [99], [100], [101]] > > The index of a string is a number. This only works because numbers > happen to have a "size" method. This nice property doesn't hold for your > example either: > > [[1,2,3],[2,3,4]].zip.unzip == [[1,2,3],[2,3,4]] > ==>true > > You can get strange results if you use "\n" in a string because "each" > iterates over the lines of a string: > > "abcdef\nABCDEFG".zip > ==>[[97, 65], [98, 66], [99, 67], [100, 68], [101, 69], [102, 70], [10, 71]] > > Strings aren't a good example of a collection anyway. ;) Heh -- maybe not, but that might also indicate that Enumerable-ness isn't a good sign of zip-ableness. Actually one reason I prefer: ary.zip(ary2, ary3) is that there's an equivalent for other Enumerables: "abc".zip("def","ghi") # => [[97, 100, 103], [98, 101, 104], [99,102, 105]] Yes, you can do this: [ "abc","def","ghi" ].zip but then you're calling zip on an array, not a string -- which then re-raises the question of why bother creating Enumerable#zip instead of Array#zip. David -- David Alan Black home: dblack@candle.superlink.net work: blackdav@shu.edu Web: http://pirate.shu.edu/~blackdav