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. This solves the problem with nil elements, too. I used catch in a previous version before I decided to first check the sizes and raise an exception. In the previous version I wanted to stop after first reaching the end of one list. The nil test was a stupid idea to find the end in the first place. > I notice that you've made this a method of Enumerable, rather than > Array. I just needed the each iterator, so Array would perhaps be to restrictive. This way its possible to iterate over a tree of objects for example if it includes Enumerable. > 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. ;) > (I gather from the original post that there was some discussion of > Enumerable#zip in the Japanese list... not sure what was said, > though, and I'm not clear on how it would work.) BTW: It would be nice to be able to pass an arbitrary iterator to zip: module Enumerable def zip(iterator = :each, &block) block ||= lambda { |*tuple| tuple } size = nil __send__(iterator) do |s| size ||= s.size s.size == size or raise "zip with unequal length lists" end result = [] i = 0 while i < size do tuple = [] __send__(iterator) do |l| tuple << l[i] end result << block.call(*tuple) i += 1 end result end end -- Poverty is an anomaly to rich people. It is very difficult to make out why people who want dinner do not ring the bell. -- Walter Bagehot