从字符串中删除字符

Lun*_*iic 5 c# csv string io

我遇到了一些非常简单的问题 - 我觉得我错过了一些非常明显的东西.

我有一个分号分隔的.csv文件.在这个文件中有几个包含像"1.300"这样的点的数字,但也包含像"2015.12.01"这样的日期.任务是找到并删除所有点,但只有那些数字而不是日期的点.日期和数字是完全可变的,永远不会在文件中的相同位置.

我现在的问题是:处理这个问题的"最佳"方法是什么?

从程序员的角度来看:它是一个很好的解决方案,只需在每个半硅上分割,计算点数,如果只有一个点,删除它?这是解决我现在想到的问题的唯一方法.


示例源文件:

2015.12.01;
13.100;
500;
1.200;
100;
Run Code Online (Sandbox Code Playgroud)

示例结果:

2015.12.01;
13100;
500;
1200;
100;
Run Code Online (Sandbox Code Playgroud)

Pat*_*man 5

如果您可以依赖日期有两个点和数字只有一个的事实,您可以将其用作过滤器:

string s = "123.45";
if (s.Count(x => x == '.') == 1)
{
    s = s.Replace(".", null);
}
Run Code Online (Sandbox Code Playgroud)


Pan*_*vos 1

源文件看起来像是由在机器上运行的程序生成的有效文件,该机器的区域设置用作.千位分隔符(欧洲大部分地区使用)和日期分隔符(我认为只有德国区域设置)。此类区域设置也用作;列表分隔符。

如果问题只是如何解析这些日期、数字,答案是将正确的区域性传递给解析函数,例如:decimal.Parse("13.500",new CultureInfo("de-at"))将返回 13500。但实际问题是数据必须馈送到另一个使用.as的程序小数点分隔符。

最安全的选择是更改导出程序使用的区域设置,例如,如果导出程序是 .NET 程序,则将线程 CultureInfo、SSIS 包中的区域设置等更改为要en-gb导出的区域设置.,并避免奇怪的日期格式。这假设管道中的下一个程序不使用德语表示日期,使用英语表示数字

另一种选择是加载文本,使用正确的区域设置解析字段,然后以下一个程序所需的格式导出它们。

最后,可以使用正则表达式仅匹配数字字段并删除点。这可能有点棘手,取决于实际内容。

例如,(\d+)\.(\d{3})如果只有一千个分隔符,则可用于匹配数字。如果某些文本字段包含相似的值,则此操作可能会失败。或者;(\d+)\.(\d{3});只能匹配除第一个和最后一个字段之外的完整字段,例如:

Regex.Replace("1.457;2016.12.30;13.000;1,50;2015.12.04;13.456",@";(\d+)\.(\d{3});",@"$1$2;")
Run Code Online (Sandbox Code Playgroud)

产生:

1.457;2016.12.3013000;1,50;2015.12.04;13.456
Run Code Online (Sandbox Code Playgroud)

;匹配第一个/最后一个字段之间的数字的正则表达式可以是

 (^|;)(\d+)\.(\d{3})(;|$)
Run Code Online (Sandbox Code Playgroud)

这会产生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+)\.(\d{3})(;|$)";
var replacement=@"$1$2$3$4";

var result= Regex.Replace(data,pattern,replacement);
Run Code Online (Sandbox Code Playgroud)

与分割和替换字符串相比,正则表达式的优点是它速度更快,内存效率更高。正则表达式不会为每个分割、操作生成临时字符串,而是仅计算源中的索引。当您请求最终文本结果时才会生成字符串对象。这会导致分配和垃圾收集少得多。

即使在中等大小的文件中,这也可以将性能提高 10 倍