比较2个字符串并将它们参数化为perl

时间:2015-02-12 02:17:08

标签: perl math expression

$s1 = 'c1 n1 n2 c = 44.3 + ( w - 2 ) * ( l - 0.5 ) * 0.836
$s2 = 'c1 n1 n2 c = 41.8 + ( w - 2 ) * ( l - 0.5 ) * 0.744

输出必须是($ s1是参考,所以,$ s2在这里给出输出)

c1 n1 n2 c = param1 + ( w - 2 ) * ( l - 0.5 ) * param2
.param1 41.8
.param2 0.744

所以,基本的想法是,在字符串之间改变的数字应该是参数化的。

----------任何想法都会很棒--------

我现在的解决方案(寻找更优雅/更好的东西):

在开头完全参数化 - 也就是说,使字符串看起来像

c1 n1 n2 c= param0 + ( w - param1 ) * ( l - param2 ) * param3

然后恢复不会更改的数字,然后重新编号参数

$count = 0
@params = ();
while( $s2 =~ s/(?<!\w)((?:[0-9.]{2,}|[0-9]+)(?:e[+-]?\d+)?)/param$count/ ){
    push( @params, $1);
    $count++;
}

然后你为$ s1做同样的事情,创建另一个数组(比方说)@ref_params。 然后是for循环来比较和恢复不变的数字..

1 个答案:

答案 0 :(得分:0)

这将假设您的字符串以空格分隔,但您可以调整拆分以适用于运算符和分组。

问题非常简单:同时逐字迭代两个字符串,遇到差异时将其转换为参数并记下s2的值。

sub parameterize {
    my @s1 = split /\s+/, shift;
    my @s2 = split /\s+/, shift;

    die "strings have different lengths" unless $#s1 == $#s2;

    my @out; 
    my @params;
    for (my $i=0; $i <= $#s1; $i++) {
        if ( $s1[$i] eq $s2[$i] ) {
            $out[$i] = $s1[$i];
        } else {
            push @params, $s2[$i];
            $out[$i] = 'param' . ($#params + 1);
        }
    }

    return join(' ', @out), map(".param@{[ $_+1 ]} $params[$_]", 0..$#params);
}

my $s1 = 'c1 n1 n2 c = 44.3 + ( w - 2 ) * ( l - 0.5 ) * 0.836';
my $s2 = 'c1 n1 n2 c = 41.8 + ( w - 2 ) * ( l - 0.5 ) * 0.744';
print join("\n", parameterize( $s1, $s2 )),"\n";

c1 n1 n2 c = param1 + ( w - 2 ) * ( l - 0.5 ) * param2
.param1 41.8
.param2 0.744