【问题标题】:c# remove zeros from middle of stringc#从字符串中间删除零
【发布时间】:2014-09-22 22:39:56
【问题描述】:

我正在使用一个 c#-4.0 Windows 窗体应用程序,我需要从序列号中删除填充零。

我的序列存储在一个字符串中,看起来像这样BMS21-14-000000000000000000120,我想要的最终结果是BMS21-14-120

序列号结构为:

  • BMS21 是前缀。
  • 14 是生产年份。
  • 120 是一个递增的数字。

现在,我们的前缀和递增数字的长度会因产品而异,但结构是一致的。它总是 prefixyearincrementing# 并且它们总是用破折号分隔。

我尝试按照msdn 概述的示例进行操作,但无法让它适用于我们的序列号。

【问题讨论】:

    标签: c# string c#-4.0 trim


    【解决方案1】:

    这是一个替代解决方案:

    static string FormatSerialNumber(string serialNumber)
    {
        var parts = serialNumber.Split('-');
        parts[2] = parts[2].TrimStart('0');
        return string.Join("-", parts);
    }
    
    // Call it like this:
    FormatSerialNumber("BMS21-14-000000000000000000120") // BMS21-14-120
    

    如果您的序列号字符串可能不严格符合此格式,您可能还需要添加代码来验证此函数的输入。

    【讨论】:

      【解决方案2】:

      这是一个适合你的单行:

      var serial = "BMS21-14-000000000000000000120";
      serial = Regex.Replace(serial, @"(?<=-\d+-)0+", String.Empty);
      

      这里有一个解释:

      • 0+ 将匹配一系列零。
      • (?&lt;=-\d+-) 是一个积极的后视 ((?&lt;=...))。它将断言零之前是一个破折号,后跟一系列数字(\d+)和另一个破折号。作为一个断言,它本身不会匹配任何东西。如果您想确保生产年份部分正好由两位数组成,\d+ 可以替换为 \d{2}

      作为旁注,您可以在0+ 之后添加(?=\d)。这是一个积极的前瞻,可以确保至少还有一位数字。这将使您将BMS21-14-000000000000000000000 减少到BMS21-14-0 而不是BMS21-14-

      【讨论】:

      • 您的正则表达式是一个不错的选择。你能解释一下这个模式吗?
      • @Marco 当然,我添加了一些解释。
      • 我不知道断言,但实际上确实需要它们。谢谢! +1。
      • @Marco 这是一个没有后视的替代方案:Regex.Replace(serial, @"(-\d+-)0+", "$1"); 只需匹配所有内容,但将年份部分保留在替换字符串中。
      • 是的,好吧,我已经考虑过好几次买那本书了。我几乎宁愿一根一根拔掉我所有的鼻毛。哈。好吧,你说服了我。刚刚通过 Amazon Prime 订购。如果它让我的大脑爆炸,我会怪你! :-)
      【解决方案3】:

      很高兴看到您自己找到了答案。但是,也许这更短:

      var parts="BMS21-14-000000000000000000120".Split('-');
      var result = string.Format("{0}-{1}-{2}", parts[0], parts[1], int.Parse(parts[2]));
      Console.WriteLine(result);
      

      【讨论】:

      • 请务必注意,这仅在字符串的最后一部分小于 int.MaxValue (2147483647) 时才有效。 long.Parse 将使您更接近序列号格式建议的最大值,但会在 long.MaxValue (9223372036854775807) 处中断
      • @p.s.w.g:有效点。在那种情况下,我需要像你这样的解决方案。为你 +1。
      【解决方案4】:
      string serial = "BMS21 - 14 - 000000000000000000120";
      
      string[] splitSerial = serial.Split('-');
      
      int code = Convert.ToInt32(splitSerial[2]);
      
      serial = splitSerial[0] + '-' + splitSerial[1] + '-' + code.ToString();
      

      【讨论】:

      • 这是恕我直言最好的答案
      【解决方案5】:

      一种扩展方法:

      public static string RemoveZeros(this string sn)
      {
          int ndx = sn.IndexOf('-');
          ndx = sn.IndexOf('-', ndx + 1);
          int cnt = ndx + 1;
          while (sn[cnt] == '0')
          {           
              cnt++;
          }
          return sn.Remove(ndx + 1, cnt - ndx - 1);
      }
      

      像这样使用它:

      string serial = "BMS21-14-000000000000000000120".RemoveZeros();
      

      【讨论】:

      • 是的,但我很确定像这样的扩展方法有点矫枉过正,因为它将应用于所有字符串,而不仅仅是目标字符串。只是想这可能也值得一提。
      • @Cyber​​herbalist,扩展方法只是提高代码可读性的语法糖(有时)。它们不会“应用于所有字符串”。它们只是 IDE 的指令“将此静态方法显示为类 X 的公共方法”(在具有扩展方法名称空间的代码中),以及编译器正确解析对它们的调用的指令。在编译代码中,它们只是静态方法。您也可以从参数中删除“this”关键字,并将这段代码用作普通的静态方法,无论如何他都是。
      • 在这个问题中:stackoverflow.com/questions/644201/… 我得到了类似的答案,但许多回答者都对扩展方法提出了警告,@rufanov。他们似乎有理由保持谨慎——也许他们没有?
      • @Cyber​​herbalist - 评论者对您的回答是错误的。扩展方法仅适用于您也想要的字符串。它不会影响所有字符串。
      • @Cyber​​herbalist,他们没有。扩展方法只是 IDE 和编译器功能。在编译后的代码中,它们只是普通的静态方法。当您键入“someClassObject”时,它们只会更改您在 IDE 自动完成功能中看到的内容。并将“使用 NamespaceWhereExtentionMethodsDefined”添加到您的代码文件中(或者如果扩展方法声明为私有,则仅在当前类中)。作为在某些类的自动完成中显示的交换,它们可以使您的代码具有更好的可读性。
      【解决方案6】:

      好的,感谢this stackoverflow post

      这是我的有效代码:

                  for (int i = 0; i < _dtSerial.Rows.Count; i++)
                  {
                      DataRow dr = _dtSerial.Rows[i];
                      string fullSer = _dtSerial.Rows[i].Field<string>("ser_num");
      
                      //Get index for the begining of the string that needs replacing
                      int foundS1 = fullSer.IndexOf("-00");
      
                      //Get index of the first non-zero value in my string
                      int foundS2 = fullSer.IndexOfAny("123456789".ToArray(), foundS1 + 1);
                      if (foundS1 != foundS2 && foundS1 >= 0)
                      {
                          fullSer = fullSer.Remove(foundS1 + 1, (foundS2 - foundS1) - 1);
                      }
                      dr["Serial"] = fullSer;
                  }
      

      获取填充零开头的索引很容易,因为它们总是以 -00 开头,但我的问题是获取第一个非零值的索引接近末尾序列号字符串。

      但后来我想出了如何使用.IndexOfAny(),它就像一个魅力。

      【讨论】:

      • 好的,但它是不必要的复杂,恕我直言。这也比 p.s.w.g. 的回答要简单得多。只是说'
      • 同意,很高兴我决定发布这个,尽管我认为我已经弄清楚了。这么多好答案,今天学到了很多!
      • 而且你用得越多,你学到的就越多!随着时间的推移,希望能在这个地方见到你。
      猜你喜欢
      • 1970-01-01
      • 2020-01-02
      • 2011-04-09
      • 2021-06-15
      • 2017-05-05
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 2014-08-04
      相关资源
      最近更新 更多