Maison > Questions et réponses > le corps du texte
P粉7648364482023-08-24 00:42:38
Essayez d'abord, utilisez simplement a-z puis 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); } } }
Notez que cela s'arrêtera à « zz ». Bien sûr, il y a quelques vilaines répétitions dans la boucle. Heureusement, c'est facile à résoudre - et cela peut être encore plus flexible :
Deuxième essai : un alphabet plus flexible
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); } } }
Maintenant, si vous souhaitez simplement générer a, b, c, d, aa, ab, ac, ad, ba, etc., vous pouvez appeler GetExcelColumns("abcd")
.
Troisième tentative (révisée davantage) - Séquence infinie
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); } }
Peut-être que l'utilisation de la récursion entraînera un code plus propre, mais ce ne sera pas aussi efficace.
Veuillez noter que si vous souhaitez vous arrêter à un point précis, vous pouvez utiliser LINQ :
var query = GetExcelColumns().TakeWhile(x => x != "zzz");
Itérateur "redémarrer"
Pour redémarrer l'itérateur à partir d'un point donné, vous pouvez utiliser SkipWhile
comme suggéré par le logicieljedi. Bien entendu, cela est assez inefficace. Si vous pouvez conserver n'importe quel état entre les appels, vous pouvez conserver l'itérateur (pour l'une ou l'autre solution) :
using (IEnumerator<string> iterator = GetExcelColumns()) { iterator.MoveNext(); string firstAttempt = iterator.Current; if (someCondition) { iterator.MoveNext(); string secondAttempt = iterator.Current; // etc } }
Alternativement, vous pourrez peut-être structurer votre code pour l'utiliser foreach
, en le cassant lorsque la première valeur pouvant réellement être utilisée est trouvée.
P粉9204852852023-08-24 00:23:16
EDIT : faites-le exactement selon la dernière modification du message original
C'est la solution la plus simple et testée :
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; }