搜尋

首頁  >  問答  >  主體

用C#遍歷字母表從a到z

<p>我有一個關於遍歷字母的問題。 我想要一個循環,從"a"開始,到"z"結束。然後,循環從"aa"開始,計數到"az"。然後從"ba"開始,一直到"bz",依此類推...</p> <p>有人知道解決辦法嗎? </p> <h2>謝謝</h2> <p>編輯:我忘了,我給一個字元"a"給函數,然後函數必須回傳"b"。如果給出"bnc",函數必須返回"bnd"。 </p>
P粉982881583P粉982881583465 天前501

全部回覆(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
  • 取消回覆