Загадка программирования: Как вы можете перевести имя столбца Excel в число? - PullRequest
46 голосов
/ 18 апреля 2009

Меня недавно попросили на собеседовании, чтобы решить загадку программирования, которой, я думаю, было бы интересно поделиться. Речь идет о переводе букв столбцов Excel в фактические числа, если вы помните, Excel называет свои столбцы буквами от A до Z, а затем последовательность идет AA, AB, AC ... AZ, BA, BB и т. Д.

Вы должны написать функцию, которая принимает строку в качестве параметра (например, «AABCCE») и возвращает фактический номер столбца.

Решение может быть на любом языке.

Ответы [ 28 ]

36 голосов
/ 17 июня 2009

Звучит как стандартное сокращение для меня:

Python:

def excel2num(x): 
    return reduce(lambda s,a:s*26+ord(a)-ord('A')+1, x, 0)

C #:

int ExcelToNumber(string x) {
    return x.Aggregate(0, (s, c) => s * 26 + c - 'A' + 1 );
}
16 голосов
/ 18 апреля 2009

Я написал это давным-давно для некоторых скриптов Python:

def index_to_int(index):
    s = 0
    pow = 1
    for letter in index[::-1]:
        d = int(letter,36) - 9
        s += pow * d
        pow *= 26
    # excel starts column numeration from 1
    return s
6 голосов
/ 18 апреля 2009

Считать имя столбца из STDIN и распечатать его соответствующий номер:

perl -le '$x = $x * 26 - 64 + ord for <> =~ /./g; print $x'

Предостережения: предполагает ASCII.

РЕДАКТИРОВАТЬ: Заменить " на ', чтобы ваша оболочка не интерполировала $x в строке.

5 голосов
/ 24 ноября 2013

По совпадению я решил ту же проблему, используя JavaScript

$(function() { //shorthand document.ready function
    var getNumber = function(x) {
        var result = 0;
        var multiplier = 1;
        for ( var i = x.length-1; i >= 0; i--)
        { 
            var value = ((x[i].charCodeAt(0) - "A".charCodeAt(0)) + 1);
            result = result + value * multiplier;
            multiplier = multiplier * 26;
        }
        return result;
    };
    
    $('#form').on('submit', function(e) { //use on if jQuery 1.7+
        e.preventDefault();  //prevent form from submitting
        var data = $("#number").val();
        $('#answer').text(getNumber(data));
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<form id="form">
<input type="text" id="number"></input>
    <button>submit</button>
</form>
<p id="answer"></p>
    var getNumber = function(x) {
        var result = 0;
        var multiplier = 1;
        for ( var i = x.length-1; i >= 0; i--)
        { 
            var value = ((x[i].charCodeAt(0) - "A".charCodeAt(0)) + 1);
            result = result + value * multiplier;
            multiplier = multiplier * 26;
        }
        return result;
    };

http://jsfiddle.net/M7Xty/1/

4 голосов
/ 18 апреля 2009

Ха-ха - написано уже в нашей кодовой базе - примерно в 3 разных раза: (

%% @doc Convert an string to a decimal integer
%% @spec b26_to_i(string()) -> integer()

b26_to_i(List) when is_list(List) ->
    b26_to_i(string:to_lower(lists:reverse(List)),0,0).

%% private functions
b26_to_i([], _Power, Value) -> 
    Value;

b26_to_i([H|T],Power,Value)->
    NewValue = case (H > 96) andalso (H < 123) of
                   true ->
                       round((H - 96) * math:pow(26, Power));
                   _    ->
                       exit([H | T] ++ " is not a valid base 26 number")
               end,
    b26_to_i(T, Power + 1, NewValue + Value).

Загадка заключается в том, что на самом деле это не представление числа в Base26 (мы лжем себе в названии нашей функции здесь), потому что в нем нет нуля.

Последовательность: A, B, C ... Z, AA, AB, AC

а не: A, B, C ... Z, BA, BB, BC

(язык Erlang, mais oui).

4 голосов
/ 17 июня 2009

Вы можете сделать это в C следующим образом:

unsigned int coltonum(char * string)
{
   unsigned result = 0;
   char ch;

   while(ch = *string++)
      result = result * 26 + ch - 'A' + 1;

  return result;
}

Нет проверки ошибок, работает только для строчных букв, строка должна заканчиваться нулем.

1 голос
/ 18 апреля 2009

Предполагая столбец A = 1

int GetColumnNumber(string columnName)
{
  int sum = 0;
  int exponent = 0;
  for(int i = columnName.Length - 1; i>=0; i--)
  {
    sum += (columnName[i] - 'A' + 1) *  (GetPower(26, exponent));
    exponent++;
  }
  return sum;
}

int GetPower(int number, int exponent)
{
  int power = 1;
  for(int i=0; i<exponent; i++)
    power *= number;
  return power;
}
1 голос
/ 08 февраля 2016

Простое Java-решение ->

public class ColumnName {

public static int colIndex(String col)
{   int index=0;
    int mul=0;
    for(int i=col.length()-1;i>=0;i--)
    {   
        index  += (col.charAt(i)-64) * Math.pow(26, mul);
        mul++;
    }
    return index;
}

public static void main(String[] args) {

    System.out.println(colIndex("AAA"));

}
1 голос
/ 06 ноября 2012

Другая Java:

public static int convertNameToIndex(String columnName) {
    int index = 0;
    char[] name = columnName.toUpperCase().toCharArray();

    for(int i = 0; i < name.length; i++) {
        index *= 26;
        index += name[i] - 'A' + 1;
    }

    return index;
}
1 голос
/ 17 июня 2009

Предостережение: обе эти версии принимают только заглавные буквы от A до Z. Все остальное вызывает просчет. Нетрудно добавить немного проверки ошибок и / или заглавных букв для их улучшения.

Скала

def excel2Number(excel : String) : Int = 
  (0 /: excel) ((accum, ch) => accum * 26 + ch - 'A' + 1)

Haskell

excel2Number :: String -> Int
excel2Number = flip foldl 0 $ \accum ch -> accum * 26 + fromEnum ch - fromEnum 'A' + 1
...