从索引生成Excel列名称


21

这是一个现实生活中的问题。当然,我们已经解决了它,但是它总是觉得它本可以做得更好,因为它太冗长和round回。但是,我的同事们都没有想到更简洁的编写方式。因此,我将其表示为代码高尔夫球。

目标是将非负整数转换为字符串,这与Excel呈现其列标题的方式相同。从而:

0 -> A
1 -> B
...
25 -> Z
26 -> AA
27 -> AB
...
51 -> AZ
52 -> BA
...
16,383 -> XFD

它必须至少工作到16,383,但是也可以接受(尽管没有奖励积分)。我最期待C#解决方案,但是,按照代码高尔夫球的传统,任何实际的编程语言都是受欢迎的。


您确定16383应该是XFD吗?676和702会得到什么?
彼得·泰勒

嗯,这就是Excel所显示的,我在网上发现它有16384列。明天我将使用我们的(众所周知的)工作代码(现在我住的地方很晚)对其进行测试。
Vilx- 2011年

此外,使用Excel本身进行测试会发现676 = ZA和702 = AAA。
Vilx- 2011年

1
我想问的原因是,我写了一些简单的基本码26,得到了这正是适合你的结果,但打破了676和702
彼得·泰勒

1
对。它不是Base-26。那就是问题所在。;)
Vilx- 2011年

Answers:



20

Excel公式:),36个字符

=SUBSTITUTE(ADDRESS(1,A1,4),"1","")

用法:

在此处输入图片说明

对不起,无法抗拒...


啊!我实际上曾想过禁止这样做,但是忘了在帖子中提到它!:D尽管如此,Excel公式仍不是编程语言(是的,Excel VBA也已超出限制)。:P
Vilx-

@ Vilx-感谢上帝,有人提出了一个较短的解决方案。我不想输入成为使用Excel公式赢得高尔夫球比赛的唯一人的历史:)
belisarius博士2011年

我仍然可以接受你的回答。>:D
Vilx- 2011年

3
<laughter type="evil">Muhahahahaha!</laughter>
Vilx- 2011年

4
您可以通过更换下降2个字节"1"1
泰勒·斯科特

9

Perl,17个字符

say[A..XFD]->[<>]

..运算符执行与神奇的自动递增相同的操作,但不需要临时变量和循环。除非strict subs在范围内,否则将裸词AXFD解释为字符串。

此答案是由匿名用户建议的,是对现有答案的修改。我认为应该将其作为一个单独的答案,并且已经做了一个答案。由于从中获得代表对我来说不公平,因此,我已使其成为Community Wiki。


由于这是目前为止最短的答案,因此我猜它应该被标记为“已接受”,直到找到更短的解决方案为止(可能仅在JonSkeetScript中可用):P具有讽刺意味。
Vilx- 2012年

1
由于关于如何完成输入和输出的问题不明确,因此实际上可以大大缩短输入时间。例如,如果输入in $_且输出是表达式的值,则(A..XFD)[$_]仅用12个char即可解决挑战。
Ilmari Karonen 2012年

抱歉,该如何运行?在perl 5.18中,当作为-E的参数给出时,它不打印任何内容。
Ed Avis

@EdAvis:它正在等待您键入数字。或者,您可以将数字放入文件中然后执行perl -E 'say[A..XFD]->[<>]' < number.txt。或者,在支持它的shell中,只需在命令行上输入即可perl -E 'say[A..XFD]->[<>]' <<< 123
Ilmari Karonen 2015年

1
我认为可以将其优化为say+(A..XFD)[<>]
Konrad Borowski

6

C,53个字符

就像用锤子打高尔夫球...

char b[4],*p=b+3;f(i){i<0||(*--p=i%26+65,f(i/26-1));}

普通版:

char b[4];
char *p = b+3;
void f(int i) {
    if (i >= 0) {
        --p;
        *p = i%26 + 65;
        f(i/26-1);
    }
}

用法是这样的:

int main(int argc, char *argv[])
{
    f(atoi(argv[1]));
    printf("%s\n", p);
    return 0;
}

5

哈斯克尔,48岁

f=(!!)(sequence=<<(tail$iterate(['A'..'Z']:)[]))

少打高尔夫球:

f n = (concatMap sequence $ tail $ iterate (['A'..'Z'] :) []) !! n

说明

Haskell的sequence组合器获取动作列表并执行它们,并在列表中返回每个动作的结果。例如:

sequence [getChar, getChar, getChar]

等效于:

do
    a <- getChar
    b <- getChar
    c <- getChar
    return [a,b,c]

在Haskell中,将动作视为值,并使用>>=(绑定)和return原语将动作粘合在一起。如果任何类型通过拥有Monad实例来实现这些运算符,则可以是“操作” 。

顺便说一句,列表类型具有monad实例。例如:

do
    a <- [1,2,3]
    b <- [4,5,6]
    return (a,b)

这等于[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]。请注意,列表理解非常相似:

[(a,b) | a <- [1,2,3], b <- [4,5,6]]

由于列表是一种“动作”,因此我们可以将其sequence与列表一起使用。以上可以表示为:

sequence [[1,2,3],[4,5,6]]

因此,sequence免费为我们提供组合!

因此,要构建列表:

["A","B"..."Z","AA","AB"]

我只需要建立要传递的清单 sequence

[['A'..'Z'],['A'..'Z','A'..'Z'],...]

然后使用concatMap既应用sequence到列表,又连接结果列表。巧合的concatMap=<<列表的功能,因此list monad也让我在这里剃了几个字符。



3

Ruby,35个字符

e=->n{a=?A;n.times{a.next!};a}

用法:

puts e[16383]   # XFD

注意:还有一个使用递归的较短版本(30个字符)。

    e=->n{n<1??A:e[n-1].next}

但是,使用此功能时,可能需要增加大量堆栈的大小,具体取决于您的ruby解释器。


3

Groovy,47岁

m={it<0?'':m(((int)it/26)-1)+('A'..'Z')[it%26]}

[0:'A',1:'B',25:'Z',
        26:'AA',
        27:'AB',
        51:'AZ',
        52:'BA',
        16383:'XFD'].collect {k,v-> assert v == m(k);m(k) }

3

Python 45 51

f=lambda i:i>=0and f(i/26-1)+chr(65+i%26)or''

您可以通过拉入+chr(65+i%26)并测试来删除2个括号,为i>=0您节省1个字符:)
quasimodo 2012年

您也可以使用f=lambda i:而不是刮掉4个字符def f(i):return
Strigoides 2012年

实际上,对于37号及以上数字来说效果不佳。我不得不对此代码进行一些更新:f = lambda i: i >= 0 and f(math.floor(i / 26 - 1)) + chr(int(round(65 + i % 26))) or ''
user007

2

Scala,62个字符

def f(i:Int):String=if(i<0)""else f((i/26)-1)+(i%26+65).toChar

用法:

println(f(16383))

返回:

XFD

您可以在Simply scala上尝试。复制并粘贴该函数并用于f(some integer)查看结果。


你并不需要""+else情况下。
彼得·泰勒

2

Excel VBA,31字节

匿名VBE立即窗口功能,它从单元格获取输入[A1]并输出到VBE立即窗口

?Replace([Address(1,A1,4)],1,"")


2

PHP,30个字节

for($c=A;$argn--;)$c++;echo$c;

与`-nr'作为管道运行或在线尝试


我很确定这不能满足要求。之后Z它会走[而不是AA
Vilx-

@ Vilx-我以此为证,证明您不太了解PHP。我加了TiO 你自己看。
泰特斯

天哪...你是对的!我确实非常了解PHP,但是它充满了怪异的东西,以至于不可能一无所知。这种特殊的怪异使我失望。在这里,请接受我的指责和歉意!
Vilx-

1

VBA / VB6 / VBScript(非Excel),73个字节

Function s(i):While i:i=i-1:s=Chr(i Mod 26+65)&s:i=i\26:Wend:End Function

呼叫s(16383)将返回XFC


欢迎来到PPCG!您可以为不熟悉VB的用户添加说明吗?
AdmBorkBork,

1
@AdmBorkBork无需过多添加到以前的答案中,只是语言绑定!
LS_ᴅᴇᴠ

i>675 - s(676)=A@@(预期YZ),s(677)=A@A(预期ZA
泰勒·斯科特

1
@TaylorScott你是对的。工作就可以了...
LS_ᴅᴇᴠ

1
@TaylorScott已更正,+ 6字节...谢谢。
LS_ᴅᴇᴠ

1

Javascript,147个字节

我有一个类似的问题。这就是解决方案。Excel列是双射基数26

n=>{f=Math.floor;m=Math.max;x=m(0,f((n-24)/676));y=m(0,f(n/26-x*26));return String.fromCharCode(...[x,y,n+1-x*676-y*26].filter(d=>d).map(d=>d+64))}

扩展,但使用1索引除外:

function getColName(colNum){ // example: 16384 => "XFD"
    let mostSig = Math.max(0, Math.floor((colNum - 26 - 1)/26**2));
    let midSig = Math.max(0, Math.floor((colNum - mostSig*26**2 - 1)/26));
    let leastSig = colNum - mostSig*26**2 - midSig*26;

    return String.fromCharCode(...[mostSig,midSig,leastSig].filter(d=>d).map(d=>d+64));
}

1
您可以添加一个TIO链接。除此之外,这是一个很好的第一答案。也欢迎来到PPCG。
穆罕默德·萨勒曼

回答7年前提出的问题也不是一个好主意。
穆罕默德·萨勒曼

好的,nvm在许多级别上都是错误的,我怎么没看到这一点
Muhammad Salman

我想问这个问题,但这是重复的。我不知道你要在@MuhammadSalman什么
MattH

一分钟后,我会尽快回复您,欢迎您使用PPCG。好答案。请注意,编写答案时,您必须提供完整的程序或功能
穆罕默德·萨尔曼

1

Java,57个字节(递归)

String f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}

在线尝试。

说明:

String f(int n){        // Recursive method with integer parameter and String return-type
  return n<0?           //  If `n` is negative:
    ""                  //   Return an empty String
   :                    //  Else:
    f(n/26-1)           //   Recursive call with `n` integer-divided by 26, minus 1
    +(char)(n%26+65);}  //   And append `n%26+65` as character

Java 10,62个字节(迭代)

n->{var r="";for(;n>=0;n=n/26-1)r=(char)(n%26+65)+r;return r;}

在线尝试。

说明:

n->{                      // Method with integer parameter and String return-type
  var r="";               //  Result-String, starting empty
  for(;n>=0;              //  Loop as long as `n` is not negative
      n=n/26-1)           //    After every iteration: divide `n` by 26, and subtract 1
    r=(char)(n%26+65)+r;  //   Prepend `n%26+65` as character to the result-String
  return r;}              //  Return the result-String

你好 抱歉,但是我偷了您的代码:在这里。:)
穆罕默德·萨尔曼

@MuhammadSalman Hehe,没问题。我实际上是从Scala答案中得到我的。;)
Kevin Cruijssen

1

第四(gforth),59字节

: f dup 0< if drop else 26 /mod 1- recurse 65 + emit then ;

在线尝试!

说明

dup 0<            \ duplicate the top of the stack and check if negative
if drop           \ if negative, drop the top of the stack
else              \ otherwise
   26 /mod        \ divide by 26 and get the quotient and remainder
   1- recurse     \ subtract one from quotient and recurse on result
   65 + emit      \ add 65 to remainder and output ascii char
then              \ exit if statement

1

R,65个字节

递归答案和许多以前的答案一样。

function(n,u=LETTERS[n%%26+1])"if"(n<=25,u,paste0(g(n%/%26-1),u))

在线尝试!


1

Powershell,68个字节

param($n)for(;$n-ge0;$n=($n-$r)/26-1){$s=[char](($r=$n%26)+65)+$s}$s

备用递归版本,68字节:

filter g{if($_-ge0){(($_-($r=$_%26))/26-1|f)+[char]($r+65)}else{''}}

测试脚本:

$f = {

param($n)for(;$n-ge0;$n=($n-$r)/26-1){$s=[char](($r=$n%26)+65)+$s}$s

}

filter g{if($_-ge0){(($_-($r=$_%26))/26-1|f)+[char]($r+65)}else{''}}


@(
    ,(0 , "A")
    ,(1 , "B")
    ,(25 , "Z")
    ,(26 , "AA")
    ,(27 , "AB")
    ,(51 , "AZ")
    ,(52 , "BA")
    ,(676 , "ZA")
    ,(702 , "AAA")
    ,(16383 , "XFD")
) | % {
    $n, $expected = $_
    $result = &$f $n
    # $result = $n|g      # Alternative
    "$($result-eq$expected): $result"
}

输出:

True: A
True: B
True: Z
True: AA
True: AB
True: AZ
True: BA
True: ZA
True: AAA
True: XFD

注意:Powershell不提供div操作员。


0

哈斯克尔,48岁

我真的以为我可以击败其他Haskell参赛者,但是a ...

f(-1)=""
f n=f(div n 26-1)++[toEnum$mod n 26+65]

我敢肯定可以剃掉几个字符,但是我已经有将近一年没有用Haskell编码了,所以我很生锈。

这并不是您所说的优雅。


不错!:)但是哈-经过3年多的时间,仍然没有C#解决方案。:D
Vilx- 2015年

哈哈,的确如此。但是使用这种相同的方法编写C#解决方案并不容易。string f(int n){return n<0?"":f(n/26-1)+(char)(n%26+65);}57个字符,因此将其发布为答案几乎会让我感到难过。
Fors 2015年

0

jQuery 1.5,71个字节

[range(1;4)as$l|[65+range(26)]|implode/""|combinations($l)]|map(add)[N]

期望输入N。例如

def N:16383;

展开:

[                       # create array with
   range(1;4) as $l     #  for each length 1,2,3
 | [65+range(26)]       #   list of ordinal values A-Z
 | implode/""           #   converted to list of strings ["A", "B", ...]
 | combinations($l)     #   generate combinations of length $l
]
| map(add)[N]           # return specified element as a string

在线尝试!



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.