【问题标题】:Parsing nested/related-value strings in functional style以函数样式解析嵌套/相关值字符串
【发布时间】:2010-09-26 18:35:32
【问题描述】:
$tasks->{t1}{cmdline} = "convert -f %FONT% %1%";
$tasks->{t1}{report} = "Launched as %CMD% by %USER%";
$tid = 't1';
foreach my $parm (keys %{$tasks->{$tid}}) {
    $tasks->{$tid}{$parm}=~s/%FONT%/$tasks->{$tid}{font}/g; # may evaluate if $parm == 'cmdline';
    $tasks->{$tid}{$parm}=~s/%CMD%/$tasks->{$tid}{cmdline}/g;
}

代码很糟糕,因为它需要在 foreach 之外进行另一个循环(以确保所有复制的值都被替换),并且还包含太多的文本数据。目前最好的重写方式如下:

foreach my $parm (keys %{$tasks->{$tid}}) {
 &lookupValues(\$tasks->{$tid}{&parm}); # or ($parm) if strict refs?
}

但是它仍然需要对键进行排序以检测优先级(如果 %CMD% 在 %FONT% 之前被替换,则 $tasks->{$tid}{report} 是错误的)。

foreach my $parm ( &SORTME($tasks->{$tid}) ) {&lookupValuesFor($tid,$parm); }

根据指定变量的数量及其关系进行排序的最佳方法是什么?原生的(很多循环和散列),或 expat [相关问题以某种方式将我指向 expat,也会对其进行调查:Parsing a string for nested patterns] 或其他解析器?

现在不喜欢 $object->value('cmdline') 的 OOP 方式。

【问题讨论】:

  • 不清楚你在担心什么。您可以使用以下命令减少$tasks->{$tid} 引用的数量:$task = $tasks->{$tid};您可以通过在“=~”运算符周围包含空格来提高可读性。如果问题是您可能对包含其他 '%XYZ%' 值的字符串进行过多(或过少)扩展,那么您需要重新考虑如何完全处理该过程。由于获得任何反馈需要一个小时,因此您可以合理地认为您的问题有些难以理解。

标签: perl nested-loops


【解决方案1】:

此代码“有效” - 对我来说看起来更干净。它是否能达到你的目标还有待商榷。

use strict;
use warnings;

my $tasks;

# Demonstration setup
$tasks->{t1}{cmdline} = "convert -f %FONT% %1%";
$tasks->{t1}{report}  = "Launched as %CMD% by %USER%";
$tasks->{t1}{maps} = {
    '%USER%'    => 'user-expansion',
    '%1%'       => 'one-expansion',
    '%FONT%'    => 'font-expansion',
    '%CMD%'     => 'cmd-expansion',
};

# Do the substitutions
foreach my $tid (keys %$tasks)
{
    my $task = $tasks->{$tid};
    my $maps = $task->{maps};
    foreach my $map (keys %$maps)
    {
        foreach my $key (keys %{$task})
        {
            next if ref $task->{$key};
            $task->{$key} =~ s/$map/$maps->{$map}/g;
        }
    }
}

# Demonstration printing
foreach my $tid (keys %$tasks)
{
    my $task = $tasks->{$tid};
    foreach my $key (keys %{$task})
    {
        next if ref $task->{$key};
        printf "%s: %-8s = %s\n", $tid, "$key:", $task->{$key};
    }
}

在 MacOS X (10.6.4) 上使用 Perl 5.13.4 的输出是:

t1: report:  = Launched as cmd-expansion by user-expansion
t1: cmdline: = convert -f font-expansion one-expansion

三重循环几乎是不可避免的;您希望将每个映射应用于每个任务的每个字符串。一般来说,每个任务都可以有自己的映射。

【讨论】:

    猜你喜欢
    • 2010-09-24
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    相关资源
    最近更新 更多