One liner: "&&" all elements of array

Discussion in 'Perl Misc' started by Irving Kimura, Feb 2, 2004.

  1. I must admit that one of the things I enjoy most about programming
    Perl is also one of the most infamous: the possibility of compact
    expressions that get a lot done with very few keystrokes. I'm
    referring to gems like this one:

    # removes duplicates from an array, preserving original order
    @no_repeats = do { my %h; grep !$h{$_}++, @has_repeats };

    ....which I found recently in an old c.l.p.m. post, and which make
    Pythonites clutch their heads and run out of the room screaming.

    OK, so call such opaque compactness a guilty pleasure, to be enjoyed
    only by consenting adults...

    I'm looking for the most compact way in Perl to take the logical
    and of all the elements of an array or list. The best I can come
    up with is this:

    !grep !$_, @array;

    (The corresponding logical or is equally long:

    !!grep $_, @array;

    The initial !! ensures a scalar result even in a list context.)

    I've also run into stuff like this

    eval join '&', map $_ ? 1 : 0, @array;

    ....which is a bit klugey but functional, and generalizable to other
    infix operators such as '|' and '+'. Then again, generalizability
    earns one no points in the compactness derby. (The map is required
    to take care of cases in which @array contains elements, such as
    the empty string or undef or whitespace, that would mess up the
    Perl string to be eval'd. And since we are now dealing with 1s
    and 0s we can take the bit-wise and.)

    I wonder if there's anything better, or I should say badder, out
    there. >:)

    Irv
     
    Irving Kimura, Feb 2, 2004
    #1
    1. Advertising

  2. Irving Kimura

    Ben Morrow Guest

    Irving Kimura <> wrote:
    >
    > # removes duplicates from an array, preserving original order
    > @no_repeats = do { my %h; grep !$h{$_}++, @has_repeats };
    >
    > ...which I found recently in an old c.l.p.m. post, and which make
    > Pythonites clutch their heads and run out of the room screaming.


    Oh, come on, that's perfectly clear... :)

    > I'm looking for the most compact way in Perl to take the logical
    > and of all the elements of an array or list. The best I can come
    > up with is this:
    >
    > !grep !$_, @array;
    >
    > (The corresponding logical or is equally long:
    >
    > !!grep $_, @array;
    >
    > The initial !! ensures a scalar result even in a list context.)


    The 'or' can be shortened by one character:

    +grep $_, @array;

    .. Other than that, I'd warrant these are the shortest for arbitrary
    operands.

    If you can guarantee 0 or 1, then "@array"!~/0/ works, with
    "@array"=~/1/ for or; if you can further guarantee $"="" then
    0+"@array" works for or.

    Ben

    --
    "The Earth is degenerating these days. Bribery and corruption abound.
    Children no longer mind their parents, every man wants to write a book,
    and it is evident that the end of the world is fast approaching."
    -Assyrian stone tablet, c.2800 BC
     
    Ben Morrow, Feb 2, 2004
    #2
    1. Advertising

  3. In <bvma8a$jni$> Ben Morrow <> writes:
    >The 'or' can be shortened by one character:


    >+grep $_, @array;


    I thought of that, but when I try

    perl -le 'print +grep $_, (1, 1)'

    I get 11 as the printout, surprisingly enough...

    After my original post, I realized that the grep-based solutions
    have an additional virtue besides brevity. They do the right thing
    if one wants to generalize the definition of the && and || operators
    to the "pathological" cases of a single operand, and no operands:

    sub And { !grep !$_, @_ }
    sub Or { !!grep $_, @_ }
    And(1) => 1
    And(0) =>
    And() => 1
    Or(1) => 1
    Or(0) =>
    Or() =>

    (There are analogous generalizations for the intersection and union
    operators in set theory.)

    So this way of implementing ands and ors is not only succinct but
    also "mathematically correct" in some sense. Even Python-heads
    have got to like that!

    Irv
     
    Irving Kimura, Feb 2, 2004
    #3
  4. Irving Kimura <> wrote:

    > I'm looking for the most compact way in Perl to



    That is called "Perl golf".

    Mentioning "golf" in your subject would help draw in
    the character-frugal type of Perl folks.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Feb 2, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mantorok Redgormor

    bitwise increment one liner

    Mantorok Redgormor, Dec 17, 2003, in forum: C Programming
    Replies:
    8
    Views:
    859
    Peter Shaggy Haywood
    Dec 19, 2003
  2. =?ISO-8859-1?Q?Morris_Carr=E9?=

    Python passes the Turing test with a one-liner !

    =?ISO-8859-1?Q?Morris_Carr=E9?=, Apr 1, 2004, in forum: Python
    Replies:
    1
    Views:
    360
    Jon Perez
    Apr 2, 2004
  3. Paul Watson

    Using for in one-liner

    Paul Watson, Aug 15, 2005, in forum: Python
    Replies:
    8
    Views:
    610
    Reinhold Birkenfeld
    Aug 17, 2005
  4. I.N. Galidakis
    Replies:
    36
    Views:
    1,499
    Gene Wirchenko
    Nov 25, 2011
  5. Larry
    Replies:
    1
    Views:
    124
    Martien Verbruggen
    Feb 3, 2005
Loading...

Share This Page