【问题标题】:Adding spaces before values in DataTable column在 DataTable 列中的值之前添加空格
【发布时间】:2020-06-30 05:00:38
【问题描述】:

我有一个 DataTable 列,其中的值包含数字和字母。例如:

  • "2A"
  • "13ABC"
  • "412BBIL"

我正在使用下面的循环在该 DataTable 中每一行的每个值之前添加空格。但是,我使用的循环计算每个字符 - 我只需要它计算数字并忽略任何非数字(如空格或特殊字符)。

为了进一步说明,"412BBIL" 有 3 位数字,"13ABC" 有 2 位数字,"2A" 有 1 位数字。

  • 在此示例"412BBIL" 中,3 位是当前最大值,并且因为它在列中具有最大位数,所以没有添加空格。
  • 因为 "13ABC" 有 2 位数字(因此比最大值少一位),它会添加一个空格 -> " 13ABC"
  • 因为 "2A" 有 1 个数字(因此比最大值少两个),它会添加 2 个空格 -> " 2A"

我的代码目前工作得非常好(但这可能不是最好的方法)——我只需要它来计算数字,而不是每个字符。如何调整下面的代码,以尽可能最有效的方式完成我需要的工作?

string maxString = dtDataTable.AsEnumerable()
    .Select(row => row["NumberColumn"].ToString())
    .OrderByDescending(st => st.Length).FirstOrDefault();

int maxStringLength = 0;    
foreach (char c in maxString)
{//Get the maximum character length in column
    if (!char.IsWhiteSpace(c))
    {
        maxStringLength++;
    }
}

//minStringLength = the minimum character length in column
int minString = 0;
int minStringLength = 9999;
for (int i = 0; i < dtDataTable.Rows.Count; i++)
{
    minString = 0;
    foreach (char c in dtDataTable.Rows[i]["NumberColumn"].ToString())
    {
        if (!char.IsWhiteSpace(c))
        {
            minString++;
        }
    }
    if ((minString <= minStringLength) && (minString != 0))
    {
        minStringLength = minString;
    }
}

//Add Spaces
int tempInt = 0;
for (int i = 0; i < dtDataTable.Rows.Count; i++)
{
    tempInt = 0;
    foreach (char c in dtDataTable.Rows[i]["NumberColumn"].ToString())
    {
        if (!char.IsWhiteSpace(c))
        {//char.IsDigit(c) might work
            tempInt++;
        }
    }

    for (int x = 0; x != (maxStringLength - tempInt); x++)
    {
        dtDataTable.Rows[i]["NumberColumn"] = " " + dtDataTable.Rows[i]["NumberColumn"].ToString();
    }
}

【问题讨论】:

  • if (char.IsDigit(c)) tempInt++; ?

标签: c# .net datatable


【解决方案1】:

使用@"^\d+" 正则表达式模式获取列中最长的数字,并将其用于PadLeft 带有您选择的填充字符的数字部分。为此,循环中的@"^(\d+)(.*)$" 正则表达式模式是捕获Match.Groups 中的数字部分和其余值以进行所需的填充,最后连接组的值以设置新值。

var cn = "NumberColumn";
var groupPatt = @"^(\d+)(.*)$";
var maxLenPatt = @"^\d+";
var paddingChar = ' ';
var maxDigitsLen = dtDataTable.AsEnumerable()
    .Select(r => Regex.Match(r.Field<string>(cn).TrimStart(paddingChar), 
    maxLenPatt).Length).Max();

foreach (var r in dtDataTable.AsEnumerable())
{
    var m = Regex.Match(r.Field<string>(cn).TrimStart(paddingChar),
        groupPatt, RegexOptions.IgnoreCase);

    if (m.Success)
        r[cn] = string.Concat(m.Groups[1].Value.TrimStart(paddingChar)
            .PadLeft(maxDigitsLen, paddingChar), m.Groups[2].Value.Trim());
}

也许:前导零而不是白人步伐?

如果您尝试在 NumberColumn 中创建固定长度的值,那么您可以改为:

var cn = "NumberColumn";
var paddingChar = '0';
var maxLen = dtDataTable.AsEnumerable().Max(r => r.Field<string>(cn).Length);

dtDataTable
    .AsEnumerable()
    .ToList()
    .ForEach(r => r[cn] = r.Field<string>(cn)
    .TrimStart(paddingChar).PadLeft(maxLen, paddingChar));

【讨论】:

  • 哦,这很酷。但是我可以问一下如何调整这段代码,以便在空格中添加(抱歉,我不知道正确的词)逻辑?因为位数是随机的,不限于3。
  • @lolikols 你好。无论是3个还是更多,目标数字是0-9插入两个空格,10-99插入一个。那是你需要的吗?或者如果长度 = 3 或更多,您需要添加一些空格? var len = Reg.... 行返回位数。不管是0还是更多。
  • 所以基本上,我需要它来匹配数字的长度。所以 9999ABC 有 4 个字符(仅限数字),例如(字符的...“检测”应该忽略空格和非数字)。所以现在,如果我有 2BCD。那是 1 个字符(同样,忽略空格和非数字)。这个想法是在字符串前面添加足够的空格,以便添加的空格数 + 位数 = 列中的最大位数。所以我们将在 2BCD 中添加 3 个空格。
  • 此外,遗憾的是,不知道该列中的最小和最大位数是多少:(。
  • @lolikols 啊哈。现在它是有道理的。我会相应地进行编辑。
【解决方案2】:
        if (!char.IsWhiteSpace(c) && !char.IsLetter(c))
        {
            tempInt++;
        }

这不是最好的方法,但它与您的原始代码保持接近。你总是可以使用正则表达式。

【讨论】:

  • 请问最好的方法是什么?抱歉 - 对编码很陌生。
  • 更新了我原来的帖子,因为我刚刚意识到我的帖子中遗漏了一大段代码。
【解决方案3】:

您可以简单地将if (char.IsDigit(c)) tempInt++; 用于数字字符。

【讨论】:

    【解决方案4】:

    严格来说,char.IsDigit 对比'0'..'9' 更多的字符返回 true,因此最好具体说明您在做什么。例如,char.IsDigit('๒') 也返回 true。如果您确实需要检测'0'..'9',那么您可以使用int digitCount = s.Count(c =&gt; '0' &lt;= c &amp;&amp; c &lt;= '9'),其中s 是您的字符串。然后,您可以使用new string(' ', digitCount) 创建一个具有所需空白量的新字符串。所以你在循环中的代码将是

    var row = dtDataTable.Rows[i];
    string s = row["NumberColumn"].ToString();
    int digitCount = s.Count(c => '0' <= c && c <= '9');
    string spaces = new string(' ', digitCount);
    row["NumberColumn"] = spaces + s;
    

    【讨论】:

    • 将 int digitCount = s.Count(c => '0'
    • 没有。它只计算“0”和“9”之间的内容。 {'0','1','2','3','4','5','6',7','8','9'} 中的任何内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 2016-11-17
    • 2018-02-07
    • 1970-01-01
    • 2017-01-22
    相关资源
    最近更新 更多