在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"]