Perl三元条件运算符

时间:2012-01-31 06:01:42

标签: perl operator-precedence conditional-operator

我正在尝试在脚本中编写更高效的代码,并且有时会实现三元条件运算符。在循环中使用三元条件运算符时,我无法理解为什么会得到额外的结果:

#!/usr/bin/perl

use strict;
use warnings;

my @array = ('Serial = "123"', 'Serial = "456"', 'Serial = "789"');
my ($test1,$test2);
foreach my $a (@array){
        !$test1 ? $test1 = $a  : $test1 .= " AND " . $a;
}
foreach my $b (@array){
        if (!$test2) {
                $test2 = $b
        } else {
                $test2 .= " AND " . $b;
        }
}
print "Test1: $test1\n";
print "Test2: $test2\n";

输出:

~/bin/test.pl
Test1: Serial = "123" AND Serial = "123" AND Serial = "456" AND Serial = "789"
Test2: Serial = "123" AND Serial = "456" AND Serial = "789"

Test1输出有一个额外的“Serial =”123“,我做错了什么?

5 个答案:

答案 0 :(得分:10)

首先,你有一个优先问题。

!$test1 ? $test1 = $a : $test1 .= " AND " . $a;

装置

( !$test1 ? $test1 = $a : $test1 ) .= " AND " . $a;

可以用parens来解决。

my $test1;
for (@array) {
   !$test1 ? ($test1 = $a) : ($test1 .= " AND " . $a);
}

但这不可读。你显然走错了方向!正在执行两项任务,您正试图将它们合二为一。简单地将它们分开可以使代码更具可读性。

my $test1;
for (@array) {
   $test1 .= ' AND ' if $test1;
   $test1 .= $_;
}

但我们还没有。让我向您介绍join

my $test1 = join(' AND ', @array);

好多了!

最后,确实看起来你正在构建一个SQL语句。如果是这样,你的问题没有实际意义,因为你应该使用地方转移数据到数据库。在DBI文档中搜索该单词。

答案 1 :(得分:7)

作业的优先级低于?。此

!$test1 ? $test1 = $a  : $test1 .= " AND " . $a;

相当于:

(!$test1 ? $test1 = $a  : $test1) .= " AND " . $a;

因此,首先$test1将成为Serial = "123",然后会立即追加AND Serial = "123"

试试这个:

!$test1 ? ($test1 = $a)  : ($test1 .= " AND " . $a);

更好的解决方案是:

$test1 = !$test1 ? $a  : $test1 . " AND " . $a;

使用三元运算符进行副作用会变得非常混乱,我建议避免使用它。

修改

正如MuIsTooShort join(' AND ', array)所指出的,在您的案例中,这将是最简洁和最易读的解决方案。

答案 2 :(得分:3)

你遇到了优先问题。您可以看到Perl如何使用Deparse

解释(即理解)表达式
perl -MO=Deparse,-p -e "!$test1 ? $test1 = $a  : $test1 .= q{ AND } . $a;"

-p告诉Deparse放入许多括号,以便您可以看到内容:

(((!$test1) ? ($test1 = $a) : $test1) .= (' AND ' . $a));

所以在这里你可以看到代码行并不意味着你的意图。

使用?:这样的风格相当糟糕,并且不会让事情变得更快。

答案 3 :(得分:2)

三元运算符适用于Z = X OR Y的情况。

你真的不是这样做的。发生的事情是你正在从数组中构建一个字符串。这就是join功能的全部内容。

my $test = join ' AND ', @array;

现在更高效的编码。

答案 4 :(得分:0)

在你的循环中

my ($test1,$test2);
foreach my $a (@array){
        !$test1 ? $test1 = $a  : $test1 .= " AND " . $a;
}

第一次$test1将是:Serial = "123" AND Serial = "123"

第二次:Serial ="123" AND Serial = "123" AND Serial = "456"

第三:Serial "123" AND Serial = "123" AND Serial = "456" AND Serial = "789"

4ht:Test1:Serial = "123" AND Serial = "123" AND Serial = "456" AND Serial = "789"