搜索

首页  >  问答  >  正文

使用C#遍历字母表从a到z

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

全部回复(2)我来回复

  • P粉764836448

    P粉7648364482023-08-24 00:42:38

    第一次尝试,只使用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,在找到第一个可以实际使用的值时中断。

    回复
    0
  • P粉920485285

    P粉9204852852023-08-24 00:23:16

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

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

    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;
    }

    回复
    0
  • 取消回复