迭代字母 - C#a-caz

sub*_*ime 16 c# iteration loops count alphabet

我有一个关于迭代字母表的问题.我想有一个以"a"开头并以"z"结尾的循环.之后,循环开始"aa"并计入"az".之后以"ba"开头直到"bz"等等......

有人知道一些解决方案吗?

谢谢

编辑:我忘了我给函数一个字符"a"然后函数必须返回b.如果你给"bnc"那么函数必须返回"bnd"

Jon*_*eet 29

第一次努力,只有az然后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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这将停在'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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果你想生成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;
        // Try to increment the least significant
        // value.
        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 we got all the way to the start of the array,
        // we need an extra value
        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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它可能是使用递归的更干净的代码,但它不会那么有效.

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

var query = GetExcelColumns().TakeWhile(x => x != "zzz");
Run Code Online (Sandbox Code Playgroud)

"重新启动"迭代器

要从给定点重新启动迭代器,您确实可以SkipWhile按照软件jedi的建议使用.当然,那效率很低.如果你能够在调用之间保持任何状态,你可以保留迭代器(对于任一解决方案):

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

    if (someCondition)
    {
        iterator.MoveNext();
        string secondAttempt = iterator.Current;
        // etc
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以构建代码以使用foreach任何方式,只需突破您可以实际使用的第一个值.

  • TheSoftwareJedi的解决方案更好,更干净.这是要使用的通用模式.可能是你被投票的原因. (2认同)

The*_*edi 22

编辑:完全按照OP的最新编辑要求完成

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

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;
}
Run Code Online (Sandbox Code Playgroud)