我正在尝试创建一种方法,在我不知道最终用户正在使用的这两种互斥方式编写数字的方式中,提供"尽力而为"的十进制输入解析:
该方法如parse_decimal(..)下面的代码中那样实现.此外,我已经定义了20个测试用例,显示了该方法的启发式方法应该如何工作.
虽然下面的代码通过了测试,但它非常可怕且难以理解.我确信有一种更紧凑和可读的方法来实现该方法.可能包括更聪明地使用正则表达式.
我的问题很简单:鉴于下面的代码和测试用例,你如何改进parse_decimal(...)以使其在传递测试时更加紧凑和可读?
澄清:
^\d{1,3}[\.,]\d{3}$含糊不清,因为人们不能逻辑地确定哪个字符用作千位分隔符,哪个字符用作小数分隔符.在不明确的情况下,我们将简单地假设使用美式小数:","作为千位分隔符和"." 作为小数分隔符.有问题的代码包括测试用例:
#!/usr/bin/perl -wT
use strict;
use warnings;
use Test::More tests => 20;
ok(&parse_decimal("1,234,567") == 1234567);
ok(&parse_decimal("1,234567") == 1.234567);
ok(&parse_decimal("1.234.567") == 1234567);
ok(&parse_decimal("1.234567") == 1.234567);
ok(&parse_decimal("12,345") == 12345);
ok(&parse_decimal("12,345,678") == 12345678);
ok(&parse_decimal("12,345.67") == 12345.67);
ok(&parse_decimal("12,34567") == 12.34567);
ok(&parse_decimal("12.34") == 12.34);
ok(&parse_decimal("12.345") == 12345);
ok(&parse_decimal("12.345,67") == 12345.67);
ok(&parse_decimal("12.345.678") == 12345678);
ok(&parse_decimal("12.34567") == 12.34567);
ok(&parse_decimal("123,4567") == 123.4567);
ok(&parse_decimal("123.4567") == 123.4567);
ok(&parse_decimal("1234,567") == 1234.567);
ok(&parse_decimal("1234.567") == 1234.567);
ok(&parse_decimal("12345") == 12345);
ok(&parse_decimal("12345,67") == 12345.67);
ok(&parse_decimal("1234567") == 1234567);
sub parse_decimal($) {
my $input = shift;
$input =~ s/[^\d,\.]//g;
if ($input !~ /[,\.]/) {
return &parse_with_separators($input, '.', ',');
} elsif ($input =~ /\d,\d+\.\d/) {
return &parse_with_separators($input, '.', ',');
} elsif ($input =~ /\d\.\d+,\d/) {
return &parse_with_separators($input, ',', '.');
} elsif ($input =~ /\d\.\d+\.\d/) {
return &parse_with_separators($input, ',', '.');
} elsif ($input =~ /\d,\d+,\d/) {
return &parse_with_separators($input, '.', ',');
} elsif ($input =~ /\d{4},\d/) {
return &parse_with_separators($input, ',', '.');
} elsif ($input =~ /\d{4}\.\d/) {
return &parse_with_separators($input, '.', ',');
} elsif ($input =~ /\d,\d{3}$/) {
return &parse_with_separators($input, '.', ',');
} elsif ($input =~ /\d\.\d{3}$/) {
return &parse_with_separators($input, ',', '.');
} elsif ($input =~ /\d,\d/) {
return &parse_with_separators($input, ',', '.');
} elsif ($input =~ /\d\.\d/) {
return &parse_with_separators($input, '.', ',');
} else {
return &parse_with_separators($input, '.', ',');
}
}
sub parse_with_separators($$$) {
my $input = shift;
my $decimal_separator = shift;
my $thousand_separator = shift;
my $output = $input;
$output =~ s/\Q${thousand_separator}\E//g;
$output =~ s/\Q${decimal_separator}\E/./g;
return $output;
}
Run Code Online (Sandbox Code Playgroud)
这就像自动猜测输入的字符编码的程序 - 它有时可能会起作用,但总的来说是一种非常糟糕的策略,导致错误和混淆的非确定性行为.
例如,如果您看到"123,456",则表示您没有足够的信息来猜测这意味着什么.
所以我会谨慎对待这个问题,并且永远不要将这种技术用于任何重要的事情.
| 归档时间: |
|
| 查看次数: |
2187 次 |
| 最近记录: |