From: Jim Weirich Date: 2008-08-06T13:51:58+09:00 Subject: [ruby-core:18140] Re: New array methods cycle, choice, shuffle (plus bug in cycle) On Aug 5, 2008, at 7:23 PM, Charles Oliver Nutter wrote: > Brian Candler wrote: >> If there are no good ideas left, perhaps things should be left as >> they are. >> Or does that make me a heretic? > > I find I frequently need to get only the second element of an array, > or perhaps the seventh. So perhaps if we have choice/pick/sample > then we should implement "second" through "tenth" as well. Maybe > also powers of ten beyond that... "tenth", "twentieth", "thirtieth". Excellent idea. Below is some code to handle ordinal numbers up to nine_hundred_ninety_nine. Provided as a mixin so you can mix it into array, or into any other class that implements the [] method. I think the use case for ordinals beyond 999 is rare enough that we don't have to include them in the standard library. > Maybe also every_other, every_third, every_fourth so I can dice my > arrays without wearing _why's flip-flops. No, I think you are wildly off base with this suggestion. However, I am considering proposing a version of Lisp's cxxxr functions (e.g. cadr, caddr) to navigate arbitrarily nested array structures. -- -- Jim Weirich -- jim.weirich@gmail.com Code below: module Ordinal class OrdinalNameError < RuntimeError end def self.ord(name, value) self.class_eval "def #{name}() self[#{value-1}] end" end def method_missing(sym, *args, &block) index = ordinal_value(sym) rescue OrdinalNameError => ex super end ORDINALS = { "and" => 0 } %w( twenty thirty fourty fifty sixty seventy eighty ninety ).each_with_index do |name, index| ORDINALS[name] = 10 * (index+2) end %w( twentieth thirtieth fortieth fiftieth sixtieth seventieth eightieth ninetieth hundredth ).each_with_index do |name, index| ORDINALS[name] = 10 * (index+2) end %w( first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth thirteenth fourteenth fifteenth sixteenth seventeenth eighteenth ninteenth twentieth ).each_with_index do |name, index| ORDINALS[name] = index + 1 end %w( one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen ).each_with_index do |name, index| ORDINALS[name] = index + 1 end def ordinal_value(name) name = name.to_s.downcase if name !~ /_/ ORDINALS[name] else terms = name.split(/_/) sum = 0 while term = terms.shift if term =~ /^hundred(th)?$/ sum *= 100 elsif ORDINALS[term] sum += ORDINALS[term] else fail OrdinalNameError, "Unknown ordinal term '#{term}'" end end sum end end end