rperlpdl

What's the equivalent of R's ifelse in Perl PDL


I am new to PDL. R's ifelse() method can do conditonal element selection. For example,

x <- c(1,2,3,4)
ifelse(x%%2, x, x*2)
# [1] 1 4 3 8

Anyone knows how to do this in PDL? I know you can do it like below, but is there any better ways?

pdl(map { $_ % 2 ? $_ : $_*2 } @{$x->unpdl} )

Solution

  • Answering the question myself. It can be something like this,

    use PDL;                                                                      
    
    sub ifelse {                                                                  
        my ( $test, $yes, $no ) = @_;                                             
    
        $test = pdl($test);                                                       
        my ( $ok, $nok ) = which_both($test);                                     
    
        my $rslt = zeros( $test->dim(0) );                                        
    
        unless ( $ok->isempty ) {                                                 
            $yes = pdl($yes);                                                     
            $rslt->slice($ok) .= $yes->index( $ok % $yes->dim(0) );               
        }                                                                         
        unless ( $nok->isempty ) {                                                
            $no = pdl($no);                                                       
            $rslt->slice($nok) .= $no->index( $nok % $no->dim(0) );               
        }                                                                         
        return $rslt;                                                             
    }                                                                             
    
    my $x = pdl( 1, 2, 3, 4 );                                                    
    say ifelse( $x % 2, $x, $x * 2 );       # [1 4 3 8]                                             
    say ifelse( $x % 2, 5, sequence( 3 ) ); # [5 1 5 0]                                      
    say ifelse( 42, $x, $x * 2 );           # [1]