以下是最有效的格式化字符串的方法?

5

我有一个非常简单的问题,不应该被卡住,但我现在卡住了。哈哈!

我收到的字符串格式如下:

123

123456-D53

123455-4D

234234-4

123415

期望的输出格式是:

123-455-444

123-455-55

123-455-5

或者

123-455

格式最终取决于原始字符串中的字符总数。

我有几种方法可以做到这一点,但我一直认为还有比string.Replace和连接更好的方法...

感谢您的建议。

Ian


6
你确定效率是这里最重要的指标,而不是可读性,例如?你进行了剖析以查看这是否是程序的瓶颈吗? - Mark Byers
1
不是这样的。事实上,我确定它不是瓶颈,效率也不是最重要的指标。我只是好奇,一整天都在思考这个问题。 :) - Ian P
5个回答

4

我应该让你知道我删除了我的回答 :-). 提问者更改了问题,它不再适用。此外,sixlettervariable指出它实际上也没有回答原始问题。 - Aryabhatta

2

编辑:查看历史版本。
您可以使用char.IsDigit()仅查找数字。

var output = new StringBuilder();
var digitCount = 0;

foreach( var c in input )
{
  if( char.IsDigit( c ) )
  {
    output.Append( c );
    digitCount++;
    if( digitCount % 3 == 0 )
    {
      output.Append( "-" );
    }
  }
}

// Remove possible last -
return output.ToString().TrimEnd('-');

这段代码应该从左到右填充(现在我明白了,先读懂再写代码)...
抱歉,我现在还无法测试它。


我认为这个填充数字的方向是错误的。他希望它左对齐,可以这样说。 - user7116
@Ian:我的解决方案删除了字母,现在...希望你需要的是这个,因为从你的问题中并不清楚(所有输出都只有数字)。 - tanascius
我不在最新的.Net上,所以这可能已经改变了,但是==“-”不应该被替换为=='-'吗? - Brian
如果你只是想简单地去掉最后一个字符,可以使用以下代码: output = output.TrimEnd('-'); - Rune FS
@Brian:谢谢,那些简单的东西我没有编译器找不到 :/ - tanascius
显示剩余3条评论

2
我假设这不仅仅依赖于输入始终是数字?如果是这样,我想到了这个:
private string ApplyCustomFormat(string input)
{
    StringBuilder builder = new StringBuilder(input.Replace("-", ""));

    int index = 3;
    while (index < builder.Length)
    {
        builder.Insert(index, "-");
        index += 4;
    }
    return builder.ToString();
}

这与我的实现类似。我只是被“这是最有效的方法吗?”这个问题困扰着。 - Ian P
@Ian P -- “最高效”不如“足够高效”重要。请看第一条评论。我会倾向于编写使用IEnumerable分块器(方法或正则表达式)和String.Join的“不太高效”的代码;-) - user166390
我选择这个作为答案,因为它按照我描述的规范首先起作用了。尽管其他帖子的作者也更新了他们的代码以满足要求。所有人都值得获得绿色勾号,但我只能选择一个 :) - Ian P

2

这里有一种方法,它使用正则表达式和LINQ的组合来提取每次三个字母的组,并将它们再次连接在一起。注意:它假设输入已经过验证。验证也可以使用正则表达式完成。

string s = "123456-D53";
string[] groups = Regex.Matches(s, @"\w{1,3}")
                       .Cast<Match>()
                       .Select(match => match.Value)
                       .ToArray();
string result = string.Join("-", groups);

结果:

123-456-D53

0

不是最快的,但很容易看懂(注:阅读):

string Normalize(string value)
{
    if (String.IsNullOrEmpty(value)) return value;

    int appended = 0;
    var builder = new StringBuilder(value.Length + value.Length/3);
    for (int ii = 0; ii < value.Length; ++ii)
    {
        if (Char.IsLetterOrDigit(value[ii]))
        {
            builder.Append(value[ii]);
            if ((++appended % 3) == 0) builder.Append('-');
        }
    }

    return builder.ToString().TrimEnd('-');
}

使用猜测来预分配StringBuilder的长度。这将接受任何字母数字输入,用户可以添加任意数量的垃圾,包括多余的空格。


6
哈哈,我们的眼光肯定不同 :p - user166390
你应该检查 (ii + 1) % 3 == 0 - Dirk Vollmar
@0xA3:干得好。@pst:如果我回来阅读这个,那么发生的事情就会很明显。没有混淆;) - user7116
你更新了代码,但还是错的;-) 所以要么检查 ((builder.Length+ 1) % 4) == 0 或者((ii + 1) % 3 == 0) - Dirk Vollmar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接