从字符串中删除字符
Posted
技术标签:
【中文标题】从字符串中删除字符【英文标题】:Delete character out of string 【发布时间】:2016-07-26 14:45:27 【问题描述】:我在完成一项非常简单的任务时遇到了一些问题 - 我觉得我在这里遗漏了一些非常明显的东西。
我有一个分号分隔的 .csv 文件。在这个文件中有几个包含点的数字,比如“1.300”,但也有一些日期,比如“2015.12.01”。任务是查找并删除所有点,但只删除那些以数字表示且不是以日期表示的点。日期和数字是完全可变的,并且不会在文件中的相同位置。
我现在的问题是:处理这个问题的“最佳”方法是什么?
从程序员的角度来看:在每个半分符处拆分,计算点数,如果只有一个点,删除它是一个好的解决方案吗?这是解决我现在能想到的问题的唯一方法。
示例源文件:
2015.12.01;
13.100;
500;
1.200;
100;
示例结果:
2015.12.01;
13100;
500;
1200;
100;
【问题讨论】:
文件中能否有不同的日期格式,例如 YYYY.MM(没有天数)? 听起来你很可能想要一个正则表达式... 这不是删除字符,这是解析文本。这不是一件容易的事。顺便说一句为什么删除点?它们是完全有效的分隔符。您是否有不同的问题,例如尝试使用错误的文化解析数字? 这可能是一个有效的问题@Pan 如果大型导出出错并且该文件只剩下您了。 @Lunatiic 为什么?如果您使用奥地利语言环境(只是使用.
进行分组和日期分隔符的国家之一),您可以使用decimal.Parse("13.100",new System.Globalization.CultureInfo("de-at"))
解析数字并获得13100
【参考方案1】:
如果您可以依赖日期有两个点和数字只有一个这一事实,则可以将其用作过滤器:
string s = "123.45";
if (s.Count(x => x == '.') == 1)
s = s.Replace(".", null);
【讨论】:
为了提高性能,最好在计算点数之前检查行长(假设格式保持不变,带日期的行应该正好是 12 个字符)。跨度> 好点@Fabjan。在这方面有很多可能的改进。 午饭后我要试试你的解决方案。提前感谢@Fabjan 日期格式始终保持 yyyy.mm.dd【参考方案2】:我不会依赖点的数量,因为可能会出错。
您可以使用double.TryParse
安全地测试字符串是否为数字
var data = "2015.12.01;13.100;500;1.200;100;";
var dataArray = data.Split(';');
foreach (var s in dataArray)
double result;
if(double.TryParse(s,out result))
// implement your logic here
Console.WriteLine(s.Replace(".",string.Empty));
【讨论】:
这很可能会引入错误。13.100
可以是 13100 或 13.100,具体取决于文化。 TryParse
永远不会失败,只是返回不同的结果【参考方案3】:
源文件看起来像是由运行在机器上的程序生成的有效文件,该机器的语言环境使用.
作为千位分隔符(欧洲大部分地区使用)和日期分隔符(我认为只有德国语言环境)。这样的语言环境也使用;
作为列表分隔符。
如果问题只是如何解析这些日期、数字,答案是将正确的文化传递给解析函数,例如:decimal.Parse("13.500",new CultureInfo("de-at"))
将返回 13500。但实际问题是必须提供数据到另一个使用.
作为小数分隔符的程序。
最安全的选择是更改导出程序使用的语言环境,例如,如果导出程序是 .NET 程序,则将线程 CultureInfo、SSIS 包中的语言环境等更改为en-gb
之类的语言环境以用于导出.
并避免奇怪的日期格式。这假设管道中的下一个程序不使用德语作为日期,使用英语作为数字
另一个选项是加载文本,使用适当的语言环境解析字段,然后以下一个程序所需的格式导出它们。
最后,正则表达式可用于仅匹配数字字段并删除点。这可能有点棘手,取决于实际内容。
例如(\d+)\.(\d3)
可用于匹配数字,如果只有一千位分隔符。如果某些文本字段包含相似的值,这可能会失败。或者;(\d+)\.(\d3);
只能匹配一个完整的字段,除了第一个和最后一个字段,例如:
Regex.Replace("1.457;2016.12.30;13.000;1,50;2015.12.04;13.456",@";(\d+)\.(\d3);",@"$1$2;")
产生:
1.457;2016.12.3013000;1,50;2015.12.04;13.456
匹配;
之间的数字或第一个/最后一个字段的正则表达式可以是
(^|;)(\d+)\.(\d3)(;|$)
这将产生1457;2016.12.30;13000;1,50;2015.12.04;13456
,例如:
var data="1.457;2016.12.30;13.000;1,50;2015.12.04;13.456";
var pattern=@"(^|;)(\d+)\.(\d3)(;|$)";
var replacement=@"$1$2$3$4";
var result= Regex.Replace(data,pattern,replacement);
与拆分和替换字符串相比,正则表达式的优势在于它很多速度更快,内存效率更高。 Regex 不会为每个拆分、操作生成临时字符串,而是仅计算源中的索引。 仅在您请求最终文本结果时生成字符串对象。这会大大减少分配和垃圾回收。
即使在中等大小的文件中,这也可以使性能提高 10 倍
【讨论】:
以上是关于从字符串中删除字符的主要内容,如果未能解决你的问题,请参考以下文章