Generate letters to represent number using ruby?

2020-05-19 02:01发布

I would like to generate a sequence of letters i.e. "A", "DE" "GJE", etc. that correspond to a number. The first 26 are pretty easy so 3 returns "C", 26 returns "Z", and 27 would return "AA", 28 "AB", and so on.

The thing I can't quite figure out is how to do this so it will handle any number passed in. So if I pass in 4123 I should get back some combination of 3 letters since (26 * 26 * 26) allows for up to +17,000 combinations.

Any suggestions?

8条回答
男人必须洒脱
2楼-- · 2020-05-19 02:35

Strings do have a succ method so they are usable in a Range. The successor to "Z" happens to be "AA", so this works:

h = {}
('A'..'ZZZ').each_with_index{|w, i| h[i+1] = w } 
p h[27] #=> "AA"
查看更多
祖国的老花朵
3楼-- · 2020-05-19 02:35
def letter_sequence(n)
    n.to_s(26).each_char.map {|i| ('A'..'Z').to_a[i.to_i(26)]}.join
end
查看更多
叼着烟拽天下
4楼-- · 2020-05-19 02:38
class Numeric
  Alph = ("a".."z").to_a
  def alph
    s, q = "", self
    (q, r = (q - 1).divmod(26)); s.prepend(Alph[r]) until q.zero?
    s
  end
end

3.alph
# => "c"
26.alph
# => "z"
27.alph
# => "aa"
4123.alph
# => "fbo"
查看更多
劳资没心,怎么记你
5楼-- · 2020-05-19 02:39

Based on sawa's answer, I wanted a method that worked independently, albeit recursively, to achieve the desired outcome:

def num_to_col(num)
  raise("invalid value #{num} for num") unless num > 0
  result, remainder = num.divmod(26)
  if remainder == 0
    result -= 1
    remainder = 26
  end
  final_letter = ('a'..'z').to_a[remainder-1]
  result > 0 ? previous_letters = num_to_col(result) : previous_letters = ''
  "#{previous_letters}#{final_letter}".upcase
end
查看更多
别忘想泡老子
6楼-- · 2020-05-19 02:44

A tweak on @sawa original answer for Ruby 2.0 since I couldn't get his to work as is:

class Numeric
  Alpha26 = ("a".."z").to_a
  def to_s26
    return "" if self < 1
    s, q = "", self
    loop do
      q, r = (q - 1).divmod(26)
      s.prepend(Alpha26[r]) 
      break if q.zero?
    end
    s
  end
end

and here it is going in reverse from string to integer:

class String
  Alpha26 = ("a".."z").to_a

  def to_i26
    result = 0
    downcased = downcase
    (1..length).each do |i|
      char = downcased[-i]
      result += 26**(i-1) * (Alpha26.index(char) + 1)
    end
    result
  end

end

Usage:

1234567890.to_s26 
# => "cywoqvj"

"cywoqvj".to_i26  
# => 1234567890

1234567890.to_s26.to_i26
# => 1234567890

"".to_i26
# => 0

0.to_s26
# => ""
查看更多
Evening l夕情丶
7楼-- · 2020-05-19 02:49

I liked this answer from: https://stackoverflow.com/a/17785576/514483

number.to_s(26).tr("0123456789abcdefghijklmnopq", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
查看更多
登录 后发表回答