Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

A more concise way to map the contents of an array.

by Amblikai (Scribe)
on Dec 30, 2012 at 12:40 UTC ( [id://1010917]=perlquestion: print w/replies, xml ) Need Help??

Amblikai has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, i'm newly registered but i've been using your site for ages. I write a lot of perl at a very basic level, (I use it for all my "data mining" at work) but i'm trying to improve my knowledge and write more concise, idiomatic code.

Anyway, i have an array, passed as reference. I want to make a new array from a slice of the referenced array, which contains only 1s or 0s depending on the value of the referenced array. In other words, i'm doing this:

my @cell_contents=map { if ($_) { 1; } else { 0; } }@$array_ref[3..10];

So if the element of the referenced array, returns as true, i want the new array element to be 1, and 0 if it returns false.

Is there a more concise way of doing this?

Thanks in advance.

Replies are listed 'Best First'.
Re: A more concise way to map the contents of an array.
by LanX (Saint) on Dec 30, 2012 at 13:03 UTC
    you could use the conditional operator aka "ternary operator" :

    my @cell_contents = map { $_ ? 1 : 0 } @$array_ref[3..10];

    another idea is to use doubled negation "!!" and to map the empty string (false) to 0.

    my @cell_contents = map { 0 + !!$_ } @$array_ref[3..10];

    but I don't think this conciseness justifies the loss of readability.¹

    Cheers Rolf

    ¹) well if you really need 0 for false.

      I don't think it gets much more concise than that. However, yet another way to achieve the same would be

      @cell_contents = map { $_ and 1 or 0 } @$array_ref[3..10]

      I like the first one you wrote, i hadn't come across that operator. Seems exactly the same as a conditional statement in Verilog. So it's still pretty readable to me!

      Regarding your footnote, supposing i didn't need 0 for false, how would i do it? And how else can you represent false?

      Thanks very much for your very helpful reply.

        > Regarding your footnote, supposing i didn't need 0 for false, how would i do it? And how else can you represent false?

        Just use the product of a doubled negation to get clear booleans!¹

        Perl's definition of false covers different data types and context cases.

        from perldata

        A scalar value is interpreted as TRUE in the Boolean sense if i +t is not the null string or the number 0 (or its string equivalent, "0") +. The Boolean context is just a special kind of scalar context where +no conversion to a string or a number is ever performed.

        (Null string here means either empty string "" or undef)

        from perlsyn

        Truth and Falsehood The number 0, the strings '0' and '', the empty list "()", and +"undef" are all false in a boolean context. All other values are true. Negation of a true value by "!" or "not" returns a special fals +e value. When evaluated as a string it is treated as '', but as a number +, it is treated as 0.

        Cheers Rolf

        ¹) in this case  my @cell_contents = map { !!$_ } @$array_ref[3..10];

        for me the most readable alternative!

Re: A more concise way to map the contents of an array.
by tobyink (Canon) on Dec 30, 2012 at 19:31 UTC
    my @cell_contents = map 1-!$_, @$array_ref[3..10];
    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1010917]
Approved by moritz
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (5)
As of 2024-03-19 10:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found