【问题标题】:In Perl, can I put unlimited conditions with the ternary conditional operator?在 Perl 中,我可以用三元条件运算符设置无限条件吗?
【发布时间】:2022-01-02 17:51:03
【问题描述】:

我对一段代码有些困惑。这是关于 perl 中的三元运算符。我不知道如何对其设置更多条件。从字面上看,我不太明白这个表达。

my $class = $user_name ? '' : (grep { $_ eq $task_id } @tasks_todo) ? 'class="todo" : 'class="crossed"';

我想用我的新变量设置另一个条件,应该是:

$required ? '' : 'class="todo"' : 'class="crossed"'

$required 是 Mojo:Collection 类型,表示由查询获取的集合类型数据。

有人可以解释一下下面的条件并告诉我是否可以对三元运算符设置另一个条件吗?允许多少个条件以及使用三元运算符的最佳实践是什么?

【问题讨论】:

  • 写这话的人太聪明了,不利于他们自己。将其拆分为更清晰的 if/else 并没有错。
  • use List::Util qw/any/; my $class = ""; unless ($user_name) { if (any { $_ eq $task_id } @tasks_todo) { $class = 'class="todo"'; } else { $class = 'class="crossed"'; } }(注意List::Util::anygrep 的更有效替代方案)
  • 恕我直言,条件运算符的最佳实践是不要在同一个表达式中使用多个。
  • 使其可读是未来维护的胜利。其中一种方法是将其分成多行,或者使用多个表达式而不是一个可能会变得太长的表达式。

标签: perl


【解决方案1】:

Whoever wrote that is too clever for their own good.

当您遇到这样的复杂逻辑时,将其拆开并放入可以单独测试的专用方法中不会丢失任何东西。通过只返回类名而不是填充的class="todo" 属性值,您可以更轻松地使用返回值,即使这意味着现在调用者有责任编写push @classes, css_class(...),后跟sprintf 'class=%s', join(' ', @classes); 或类似的。

#!/usr/bin/env perl

use strict;
use warnings;

use List::Util qw( any );
use Test::More;

sub css_class {
    my ($user_name, $task_id, $tasks_todo) = @_;

    return '' unless $user_name;

    if (any { $task_id eq $_ } $tasks_todo->@*) {
        return 'todo';
    }

    return 'crossed';
}

my @cases = (
    {
        args => [undef, 'blah', []],
        expected => '',
    },
    {
        args => ['bob', 'notdone', ['notdone']],
        expected => 'todo',
    },
    {
        args => ['bob', 'done', ['notdone']],
        expected => 'crossed',
    },
);

for my $case (@cases) {
    is css_class($case->{args}->@*), $case->{expected};
}

done_testing;

输出:

$ prove -v pp.pl
pp.pl ..
ok 1
ok 2
ok 3
1..3
ok
All tests successful.
Files=1, Tests=3,  0 wallclock secs ( 0.08 usr +  0.03 sys =  0.11 CPU)
Result: PASS

【讨论】:

    【解决方案2】:

    如果设置了 $username,则 $class-Variable 设置为空, 否则,如果 $task_id 在 @task_todos 中,$class 设置为 'class="todo"',如果两者都不为真,则 $class 设置为 'class="crossed"'。

    您可以使用三元运算符在表达式中添加任意数量的条件,但您应该考虑至少添加一些空格以使其更具可读性,尽管将其放入 if/then/else 会更好。

    my $class = $user_name 
                 ? ''  
                   : (grep { $_ eq $task_id } @tasks_todo) 
                      ? 'class="todo"'
                        : 'class="crossed"';
    

    【讨论】:

      【解决方案3】:

      我通过在前面给出的示例之后添加一个新条件来解决我的问题。

      use List::Util qw/any/;
      my $class = "";
      unless ($user_name) {
         if (any { $_ eq $task_id } @tasks_todo) {
            $class = 'class="todo"'; 
         } 
         else
         {
           $class = 'class="crossed"';
         }
         if ($required ne $month) {
           $class = 'class="crossed"'
      }
      

      这成功了,要么我改变了我的查询,所以我得到了正确的东西。

      【讨论】:

      猜你喜欢
      • 2012-02-22
      • 2016-10-27
      • 2020-03-18
      • 2018-09-29
      • 2023-04-11
      • 1970-01-01
      • 2018-03-13
      • 2022-01-06
      相关资源
      最近更新 更多