【问题标题】:Incrementing alphabets递增字母
【发布时间】:2010-10-29 18:36:04
【问题描述】:

我正在尝试创建一个函数,该函数将在传递索引时为我提供字母位置。它将与 excel 如何显示它的列相同。 A...Z, AA,AB.... 我写了下面的函数来得到 Z 的结果。它看起来像

static string GetColumnName(int index)
{
    const int alphabetsCount = 26;
    if (index <= alphabetsCount)
    {
        int code = (index - 1) + (int)'A';
        return char.ConvertFromUtf32(code);
    }
    return string.Empty;
}

这在“Z”之前都可以正常工作。如果我通过 1 则返回“A”,如果通过 2 则返回“B”,依此类推。但是,当我将 27 传递给此函数时,我无法弄清楚如何获得 AA。我想我需要一种递归方法来找到它。

对这个问题的任何输入都会很棒!

编辑

这是 Tordek 建议的。但是他的代码会在 52、78 等数字上失败。为此添加了解决方法,这是最终的工作代码。

static string GetColumnName(int index)
{
    const int alphabetsCount = 26;

    if (index > alphabetsCount)
    {
        int mod = index % alphabetsCount;
        int columnIndex = index / alphabetsCount;

        // if mod is 0 (clearly divisible) we reached end of one combination. Something like AZ
        if (mod == 0)
        {
            // reducing column index as index / alphabetsCount will give the next value and we will miss one column.
            columnIndex -= 1;
            // passing 0 to the function will return character '@' which is invalid
            // mod should be the alphabets count. So it takes the last char in the alphabet.
            mod = alphabetsCount;
        }
        return GetColumnName(columnIndex) + GetColumnName(mod);
    }
    else
    {
        int code = (index - 1) + (int)'A';
        return char.ConvertFromUtf32(code);
    }
}

【问题讨论】:

    标签: c# alphabet


    【解决方案1】:

    任何递归函数都可以转换为等效的迭代函数。我发现首先递归思考总是很容易:

    static string GetColumnName(int index)
    {
        const int alphabetsCount = 26;
    
        if (index > alphabetsCount) {
            return GetColumnName(index / alphabetsCount) + GetColumnName(index % alphabetsCount);
        } else {
            int code = (index - 1) + (int)'A';
            return char.ConvertFromUtf32(code);
        }
    }
    

    可以简单转换成:

    static string GetColumnName(int index)
    {
        const int alphabetsCount = 26;
        string result = string.Empty;
    
        while (index > 0) {
            result = char.ConvertFromUtf32(64 + (index % alphabetsCount)) + result;
            index /= alphabetsCount;
        }
    
        return result;
    }
    

    即便如此,听乔尔的话。

    【讨论】:

    • 太棒了。我的数学生锈了。所以无法弄清楚模运算。感谢您的代码。
    【解决方案2】:

    看到这个问题:
    Translate a column index into an Excel Column Name

    或者这个:
    How to convert a column number (eg. 127) into an excel column (eg. AA)

    虽然第一个链接在顶部有一个正确的答案,而第二个有几个不正确的答案。

    【讨论】:

      【解决方案3】:
      静态字符串 GetColumnName(int index) { 常量 int 字母计数 = 26; 字符串结果 = ''; 如果(索引 >= 字母计数) { 结果 += GetColumnName(index-alphabetsCount) } 返回(字符串)(64 + 索引); }

      我的 C# 很糟糕而且生锈。将其解释为伪代码 - 它几乎肯定不会编译,但可以帮助您入门。

      【讨论】:

        【解决方案4】:

        递归是一种可能性——如果index &gt; 26,您在此调用中处理index % 26,并将其连接到index / 26 上的递归调用。然而,迭代通常更快,并且不难安排像这样的简单情况。在伪代码中:

        string result = <convert `index % 26`>
        while index > 26:
          index = index / 26
          result = <convert `index % 26`> + result
        return result
        

        或类似的。

        【讨论】:

        • 您的伪代码没有任何问题,但重要的是要知道,如果您要在循环中附加到字符串,您可能应该使用 StringBuilder 类,以节省对象分配:@ 987654321@
        • 这是错误的,因为它不是base 26 系统。如果 A 为 0,则 A 等于 AA (0 == 00)。如果 A 为 1,则从 Z 到 AA 就像从 9 到 11。
        • 保罗,StringBuilder 太过分了。 32 位 int 是 2^32 并且 26^7 溢出它,因此最大值为 7 个字母长。 7 次迭代几乎不费力。一个 64 位的长度只有 14 个字母。 :)
        猜你喜欢
        • 2016-09-05
        • 1970-01-01
        • 1970-01-01
        • 2017-11-03
        • 2014-10-08
        • 1970-01-01
        • 2011-07-21
        • 2011-03-31
        • 1970-01-01
        相关资源
        最近更新 更多