使用C#遍历字母表从a到z
P粉982881583
P粉982881583 2023-08-23 09:51:55
0
2
496
<p>我有一个关于遍历字母表的问题。 我想要一个循环,从"a"开始,到"z"结束。然后,循环从"aa"开始,计数到"az"。然后从"ba"开始,一直到"bz",依此类推...</p> <p>有人知道解决办法吗?</p> <h2>谢谢</h2> <p>编辑:我忘记了,我给出一个字符"a"给函数,然后函数必须返回"b"。如果给出"bnc",函数必须返回"bnd"。</p>
P粉982881583
P粉982881583

全部回复(2)
P粉764836448

第一次尝试,只使用a-z然后是aa-zz

public static IEnumerable<string> GetExcelColumns()
{
    for (char c = 'a'; c <= 'z'; c++)
    {
        yield return c.ToString();
    }
    char[] chars = new char[2];
    for (char high = 'a'; high <= 'z'; high++)
    {
        chars[0] = high;
        for (char low = 'a'; low <= 'z'; low++)
        {
            chars[1] = low;
            yield return new string(chars);
        }
    }
}

请注意,这将在'zz'处停止。当然,循环中存在一些丑陋的重复。幸运的是,这很容易解决 - 并且它还可以更加灵活:

第二次尝试:更灵活的字母表

private const string Alphabet = "abcdefghijklmnopqrstuvwxyz";

public static IEnumerable<string> GetExcelColumns()
{
    return GetExcelColumns(Alphabet);
}

public static IEnumerable<string> GetExcelColumns(string alphabet)
{
    foreach(char c in alphabet)
    {
        yield return c.ToString();
    }
    char[] chars = new char[2];
    foreach(char high in alphabet)
    {
        chars[0] = high;
        foreach(char low in alphabet)
        {
            chars[1] = low;
            yield return new string(chars);
        }
    }
}

现在,如果你只想生成a、b、c、d、aa、ab、ac、ad、ba等,你可以调用GetExcelColumns("abcd")

第三次尝试(进一步修订)- 无限序列

public static IEnumerable<string> GetExcelColumns(string alphabet)
{
    int length = 0;
    char[] chars = null;
    int[] indexes = null;
    while (true)
    {
        int position = length-1;
        // 尝试递增最低有效值。
        while (position >= 0)
        {
            indexes[position]++;
            if (indexes[position] == alphabet.Length)
            {
                for (int i=position; i < length; i++)
                {
                    indexes[i] = 0;
                    chars[i] = alphabet[0];
                }
                position--;
            }
            else
            {
                chars[position] = alphabet[indexes[position]];
                break;
            }
        }
        // 如果我们到达数组的开始位置,我们需要一个额外的值
        if (position == -1)
        {
            length++; 
            chars = new char[length];
            indexes = new int[length];
            for (int i=0; i < length; i++)
            {
                chars[i] = alphabet[0];
            }
        }
        yield return new string(chars);
    }
}

可能使用递归会有更清晰的代码,但效率不会那么高。

请注意,如果你想在某个特定点停止,你可以使用LINQ:

var query = GetExcelColumns().TakeWhile(x => x != "zzz");

“重新启动”迭代器

要从给定点重新启动迭代器,你可以像thesoftwarejedi建议的那样使用SkipWhile。当然,这相当低效。如果你能在调用之间保持任何状态,你可以保留迭代器(对于任一解决方案):

using (IEnumerator<string> iterator = GetExcelColumns())
{
    iterator.MoveNext();
    string firstAttempt = iterator.Current;

    if (someCondition)
    {
        iterator.MoveNext();
        string secondAttempt = iterator.Current;
        // etc
    }
}

或者,你可能能够构建你的代码以使用foreach,在找到第一个可以实际使用的值时中断。

P粉920485285

编辑:使其完全按照原始帖子的最新编辑要求执行

这是最简单的解决方案,并经过测试:

static void Main(string[] args)
{
    Console.WriteLine(GetNextBase26("a"));
    Console.WriteLine(GetNextBase26("bnc"));
}

private static string GetNextBase26(string a)
{
    return Base26Sequence().SkipWhile(x => x != a).Skip(1).First();
}

private static IEnumerable<string> Base26Sequence()
{
    long i = 0L;
    while (true)
        yield return Base26Encode(i++);
}

private static char[] base26Chars = "abcdefghijklmnopqrstuvwxyz".ToCharArray();
private static string Base26Encode(Int64 value)
{
    string returnValue = null;
    do
    {
        returnValue = base26Chars[value % 26] + returnValue;
        value /= 26;
    } while (value-- != 0);
    return returnValue;
}
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板