在A之后开始并在Z之后结束时创建一系列字母的数组即(B到AC)

我正在使用Roo Gem并希望从基于标准A1语法的电子表格中提取数据。

我在Z以外的电子表格中有列,因此Excel可以完成整个AA,AB,AC列位置。

我想为列W到AH创建一个数组。

当上限延伸超过Z但是没有从A开始时,Ruby似乎不喜欢

任何想法如何("B".."AC").to_a而不是得到[]

这是irb的基本问题。

 ("A".."Z").to_a #=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] ("B".."Z").to_a #=> ["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] ("A".."AC").to_a #=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC"] ("B".."AC").to_a #=> [] 

这个怎么样?

 ("A".."AC").to_a.drop(1) 

你可以删除你喜欢的任何数量的elements ,它只涉及1个范围和1个数组创建..

整数可能会替换为返回字母表中字母位置的某些内容。

 class Array def from(column) drop(find_index(column).to_i) end end ("A".."AC").to_a.from('F') #=> ["F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC"] 

直接使用Range类,感谢@ sagarpandya82

 class Range def from(column) to_a.drop(find_index(column).to_i) end end ("A".."AC").from('F') #=> ["F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC"] 

使用Kernel#loop建立一个空数组。 一旦当前值等于第二个参数,循环就会中断。 要返回新构建的数组o ,我们将o作为参数传递给break ,默认情况下返回nil

 def cols a, b loop.with_object([]) do |_, o| o << a break(o) if a == b a = a.next end end cols('W','AH') #=> ["W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH"] cols("A","Z") #=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", # "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] cols("B","Z") #=> ["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", # "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] cols("A","AC") #=> ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", # "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", # "AA", "AB", "AC"] cols("B","AC") #=> ["B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", # "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", # "AB", "AC"] 

对此的数学答案是:

A => AH =(A => W)+(W => AH)

所以W => AH =(A => AH) – (A => W)

这个程序化答案:

 ("A".."AH").to_a - ("A"..."W").to_a #=> ["W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH"] 

...在第二个范围内使其独占,即没有“W”。

更一般的答案是

 r = "W".."AH" ("A"..r.end).to_a - ("A"...r.begin).to_a #=> ["W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH"] 

Ruby的String#succ以Excel递增列名的方式递增字母:

 'Z'.succ #=> "AA" 

因此,如果您知道目标值可通过succ访问,则一个简单的循环可以工作:

 ary = ['W'] ary << ary.last.succ until ary.last == 'AH' ary #=> ["W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH"] 

但是如果使用错误的值,它很容易变成无限循环。


要获得更强大的解决方案,您可以编写自定义类:

 class Column attr_reader :name def initialize(name) raise ArgumentError if name =~ /[^AZ]/ @name = name end def <=>(other) [name.length, name] <=> [other.name.length, other.name] end def succ Column.new(name.succ) end end 

它基本上只包装列名,但它也考虑了名称的length

 [name.length, name] <=> [other.name.length, other.name] 

这意味着较长的名字来自较短的名字。 具有相同长度的名称按字典顺序进行比较。

这允许您生成所需的序列:

 r = Column.new('W')..Column.new('AH') r.map(&:name) #=> ["W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH"]