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

Can I shorten the following code into one statement?
for (@point_names) { s/"//; s/;//; s/^\s+//; s/ //; }

Replies are listed 'Best First'.
Re: shortening substitutions
by Thilosophy (Curate) on Jun 17, 2005 at 11:25 UTC
    Why do you want to do that? These four statements are very readable, combining them into one complex one would result in less readily understandable code.

    In addition to that, I think an equivalent single regex would be tricky to think of. Just consider the delicate details:

    • You want to match each substituation only once. One quotation mark, one semicolon, leading white-space, one group of exactly four spaces.
    • The order in which you do these substitutions is relevant. Non-leading spaces can become leading spaces by stripping away a quotation mark, for example (which could also combine runs of spaces into four spaces).
    Trying to preserve all that in a single statement makes my head hurt.

    Some of these complexities are maybe in error. I do not know what you are trying to do, of course, but perhaps you want to strip all quotation marks, not only the first one. Once you need to debug code, four simple regex are easier to grasp than one complex regex.

    So, I would suggest to stick with what you have now.

Re: shortening substitutions
by Anonymous Monk on Jun 17, 2005 at 12:25 UTC
    One statement? Sure:
    s/"//, s/;//, s/^\s+//, s/ // for @point_names;
Re: shortening substitutions
by prasadbabu (Prior) on Jun 17, 2005 at 10:59 UTC

    How about this,

    s/((^\s+)|\s{4}|[";]+)+// for (@point_names);

    tlm your are correct.It depends on the input string.
    Updated: As per tlm instruction.

    Prasad

      No, this can results in as few as 1 substitution on input strings for which the original can produce up to four. (thundergnat's solution has similar problems.) I don't see the advantage of doing what the OP requests.

      the lowliest monk

Re: shortening substitutions
by grinder (Bishop) on Jun 17, 2005 at 13:25 UTC

    The first two can be dealt with using tr

    tr/";//d;

    update: except of course that it can't: tr/// will perform all such transliterations, not merely the first. If indeed only the first such match found should undergo substition and not the rest, then you're not going to get any more compact than the original code.

    If the last s/// is to remove tabs, then you can add \t to the left-hand side of the above tr///. In any event, for performance reasons you want to leave the s/^\s+// by itself.

    If you are brave and insist on this approach, you could try folding the rest into:

    update: oops, seriously lagged here, and as pointed out, the following doesn't perform according to spec. The tr/// stuff still holds, though.

    s/(?:     |[";])//

    but I don't think it's as readadble. You could even add the ^\s+ as another alternation, but it would not be as efficient.

    - another intruder with the mooring in the heart of the Perl

      tr/";//d; is not equivalent to s/[";]//; but to s/[";]//g; !!!
Re: shortening substitutions
by thundergnat (Deacon) on Jun 17, 2005 at 11:10 UTC
    s/^\s+|\s{4}|[";]//; or possibly s/^\s+|\s{4,}|[";]//;

    if you want to get rid of 4 or more spaces

      well, this is not equivalent to the OP code. For instance, try applying both to qq("   " foo  ;  )

      Anyway, I'm sure the OP code is missing some /.../g regexp modifiers. He should tell us what he really wants to do, and why he wants to write it on a single statement after all.