在 C# 中生成字母序列的逻辑
Logic to generate an alphabetical sequence in C#
顺序应该是这样的。
A-Z,AA-AZ,BA-BZ,CA-CZ,......,ZA-ZZ
在 ZZ 之后应该从 AAA.
开始
然后 AAA 到 ZZZ 然后 AAAA 到 ZZZZ 和等等。
这个序列与 Excel sheet 的序列非常相似。
编辑:添加了我的代码
private void SequenceGenerator()
{
var numAlpha = new Regex("(?<Numeric>[0-9]*)(?<Alpha>[a-zA-Z]*)");
var match = numAlpha.Match(txtBNo.Text);
var alpha = match.Groups["Alpha"].Value;
var num = Convert.ToInt32(match.Groups["Numeric"].Value);
lastChar = alpha.Substring(alpha.Length - 1);
if (lastChar=="Z")
{
lastChar = "A";
txtBNo.Text = num.ToString() + "A" + alpha.Substring(0, alpha.Length - 1) + lastChar;
}
else
{
txtBNo.Text = num.ToString() + alpha.Substring(0, alpha.Length - 1) + Convert.ToChar(Convert.ToInt32(Convert.ToChar(lastChar)) + 1);
}
}
这就是我所做的。但是,我知道这是一个错误的逻辑。
谢谢。
正如我在评论中所写,这是一个基础转换问题,您的输出在 base-26 中,符号为 A-Z
static string NumToLetters(int num)
{
string str = string.Empty;
// We need to do at least a "round" of division
// to handle num == 0
do
{
// We have to "prepend" the new digit
str = (char)('A' + (num % 26)) + str;
num /= 26;
}
while (num != 0);
return str;
}
幸运的是,我以前做过一次。我遇到的问题是 Excel sheet 中没有 0,甚至在 double 'digit' 'numbers' 中也没有。这意味着您从 a(即 1)开始,然后从 z(即 26)开始直接进入 aa(27)。这就是为什么 不是一个简单的基本转换问题 ,并且您需要一些额外的代码来处理这个问题。
使用以下结果测试 xanatos 建议的功能:
NumToLetters(0) --> A
NumToLetters(25) --> Z
NumToLetters(26) --> BA
我的解决方案有更多代码,但它已经针对 Excel 进行了测试并且完全兼容,除了它以 0 而不是 1 开头,这意味着 a 是 0,z 是 25,aa 是 26,zz 701,aaa 是 702 等等)。如果你愿意,你可以把它改成从1开始,这很容易。
private static string mColumnLetters = "zabcdefghijklmnopqrstuvwxyz";
// Convert Column name to 0 based index
public static int ColumnIndexByName(string ColumnName)
{
string CurrentLetter;
int ColumnIndex, LetterValue, ColumnNameLength;
ColumnIndex = -1; // A is the first column, but for calculation it's number is 1 and not 0. however, Index is alsways zero-based.
ColumnNameLength = ColumnName.Length;
for (int i = 0; i < ColumnNameLength; i++)
{
CurrentLetter = ColumnName.Substring(i, 1).ToLower();
LetterValue = mColumnLetters.IndexOf(CurrentLetter);
ColumnIndex += LetterValue * (int)Math.Pow(26, (ColumnNameLength - (i + 1)));
}
return ColumnIndex;
}
// Convert 0 based index to Column name
public static string ColumnNameByIndex(int ColumnIndex)
{
int ModOf26, Subtract;
StringBuilder NumberInLetters = new StringBuilder();
ColumnIndex += 1; // A is the first column, but for calculation it's number is 1 and not 0. however, Index is alsways zero-based.
while (ColumnIndex > 0)
{
if (ColumnIndex <= 26)
{
ModOf26 = ColumnIndex;
NumberInLetters.Insert(0, mColumnLetters.Substring(ModOf26, 1));
ColumnIndex = 0;
}
else
{
ModOf26 = ColumnIndex % 26;
Subtract = (ModOf26 == 0) ? 26 : ModOf26;
ColumnIndex = (ColumnIndex - Subtract) / 26;
NumberInLetters.Insert(0, mColumnLetters.Substring(ModOf26, 1));
}
}
return NumberInLetters.ToString().ToUpper();
}
试试这个方法:
public static IEnumerable<string> GenerateItems()
{
var buffer = new[] { '@' };
var maxIdx = 0;
while(true)
{
var i = maxIdx;
while (true)
{
if (buffer[i] < 'Z')
{
buffer[i]++;
break;
}
if (i == 0)
{
buffer = Enumerable.Range(0, ++maxIdx + 1).Select(c => 'A').ToArray();
break;
}
buffer[i] = 'A';
i--;
}
yield return new string(buffer);
}
// ReSharper disable once FunctionNeverReturns
}
这是您需要的按字母顺序排列的无限生成器,您必须像这样限制项目的数量:
var sequence = GenerateItems().Take(10000).ToArray();
不要这样调用(会死循环):
foreach (var i in GenerateItems())
Console.WriteLine(i);
顺序应该是这样的。
A-Z,AA-AZ,BA-BZ,CA-CZ,......,ZA-ZZ
在 ZZ 之后应该从 AAA.
开始
然后 AAA 到 ZZZ 然后 AAAA 到 ZZZZ 和等等。
这个序列与 Excel sheet 的序列非常相似。
编辑:添加了我的代码
private void SequenceGenerator()
{
var numAlpha = new Regex("(?<Numeric>[0-9]*)(?<Alpha>[a-zA-Z]*)");
var match = numAlpha.Match(txtBNo.Text);
var alpha = match.Groups["Alpha"].Value;
var num = Convert.ToInt32(match.Groups["Numeric"].Value);
lastChar = alpha.Substring(alpha.Length - 1);
if (lastChar=="Z")
{
lastChar = "A";
txtBNo.Text = num.ToString() + "A" + alpha.Substring(0, alpha.Length - 1) + lastChar;
}
else
{
txtBNo.Text = num.ToString() + alpha.Substring(0, alpha.Length - 1) + Convert.ToChar(Convert.ToInt32(Convert.ToChar(lastChar)) + 1);
}
}
这就是我所做的。但是,我知道这是一个错误的逻辑。
谢谢。
正如我在评论中所写,这是一个基础转换问题,您的输出在 base-26 中,符号为 A-Z
static string NumToLetters(int num)
{
string str = string.Empty;
// We need to do at least a "round" of division
// to handle num == 0
do
{
// We have to "prepend" the new digit
str = (char)('A' + (num % 26)) + str;
num /= 26;
}
while (num != 0);
return str;
}
幸运的是,我以前做过一次。我遇到的问题是 Excel sheet 中没有 0,甚至在 double 'digit' 'numbers' 中也没有。这意味着您从 a(即 1)开始,然后从 z(即 26)开始直接进入 aa(27)。这就是为什么 不是一个简单的基本转换问题 ,并且您需要一些额外的代码来处理这个问题。 使用以下结果测试 xanatos 建议的功能:
NumToLetters(0) --> A
NumToLetters(25) --> Z
NumToLetters(26) --> BA
我的解决方案有更多代码,但它已经针对 Excel 进行了测试并且完全兼容,除了它以 0 而不是 1 开头,这意味着 a 是 0,z 是 25,aa 是 26,zz 701,aaa 是 702 等等)。如果你愿意,你可以把它改成从1开始,这很容易。
private static string mColumnLetters = "zabcdefghijklmnopqrstuvwxyz";
// Convert Column name to 0 based index
public static int ColumnIndexByName(string ColumnName)
{
string CurrentLetter;
int ColumnIndex, LetterValue, ColumnNameLength;
ColumnIndex = -1; // A is the first column, but for calculation it's number is 1 and not 0. however, Index is alsways zero-based.
ColumnNameLength = ColumnName.Length;
for (int i = 0; i < ColumnNameLength; i++)
{
CurrentLetter = ColumnName.Substring(i, 1).ToLower();
LetterValue = mColumnLetters.IndexOf(CurrentLetter);
ColumnIndex += LetterValue * (int)Math.Pow(26, (ColumnNameLength - (i + 1)));
}
return ColumnIndex;
}
// Convert 0 based index to Column name
public static string ColumnNameByIndex(int ColumnIndex)
{
int ModOf26, Subtract;
StringBuilder NumberInLetters = new StringBuilder();
ColumnIndex += 1; // A is the first column, but for calculation it's number is 1 and not 0. however, Index is alsways zero-based.
while (ColumnIndex > 0)
{
if (ColumnIndex <= 26)
{
ModOf26 = ColumnIndex;
NumberInLetters.Insert(0, mColumnLetters.Substring(ModOf26, 1));
ColumnIndex = 0;
}
else
{
ModOf26 = ColumnIndex % 26;
Subtract = (ModOf26 == 0) ? 26 : ModOf26;
ColumnIndex = (ColumnIndex - Subtract) / 26;
NumberInLetters.Insert(0, mColumnLetters.Substring(ModOf26, 1));
}
}
return NumberInLetters.ToString().ToUpper();
}
试试这个方法:
public static IEnumerable<string> GenerateItems()
{
var buffer = new[] { '@' };
var maxIdx = 0;
while(true)
{
var i = maxIdx;
while (true)
{
if (buffer[i] < 'Z')
{
buffer[i]++;
break;
}
if (i == 0)
{
buffer = Enumerable.Range(0, ++maxIdx + 1).Select(c => 'A').ToArray();
break;
}
buffer[i] = 'A';
i--;
}
yield return new string(buffer);
}
// ReSharper disable once FunctionNeverReturns
}
这是您需要的按字母顺序排列的无限生成器,您必须像这样限制项目的数量:
var sequence = GenerateItems().Take(10000).ToArray();
不要这样调用(会死循环):
foreach (var i in GenerateItems())
Console.WriteLine(i);