【问题标题】:Perl ternary conditional operatorPerl 三元条件运算符
【发布时间】:2012-02-22 21:51:39
【问题描述】:

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

#!/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”,我做错了什么?

【问题讨论】:

  • 三元条件运算符不会使您的代码更高效。它使它可读性降低。我什至不知道在 .= 运算符的左侧嵌入赋值的三元条件运算符意味着什么,更不用说它是否能正常工作了。
  • 你为什么要以这种奇怪的方式重新实现join

标签: perl operator-precedence conditional-operator


【解决方案1】:

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

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

意思

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

可以用括号解决。

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 文档中搜索该词。

【讨论】:

    【解决方案2】:

    分配的优先级低于?。这个

    !$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) 所述,在您的情况下,这将是最简洁易读的解决方案。

    【讨论】:

      【解决方案3】:

      您遇到了优先级问题。您可以看到 Perl 如何使用 Deparse 解释(即理解)表达式

      perl -MO=Deparse,-p -e "!$test1 ? $test1 = $a  : $test1 .= q{ AND } . $a;"
      

      -p 告诉 Deparse 放入很多括号,以便您查看发生了什么:

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

      所以在这里你可以看到这行代码并不代表你想要的。

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

      【讨论】:

        【解决方案4】:

        三元运算符非常适合Z = X OR Y 的情况。

        你在这里并没有真正做到这一点。发生的事情是您正在从数组构建一个字符串。这就是join 函数的全部意义所在。

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

        现在 编码效率更高。

        【讨论】:

          【解决方案5】:

          在你的循环中

          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"

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2010-09-05
            • 2013-04-26
            • 2013-06-06
            • 2021-11-04
            • 2023-04-11
            • 2015-05-20
            • 2020-01-18
            相关资源
            最近更新 更多