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

I have an array which is content of website..
I want to know how to extract unique elements in the array which are more than 4 characters in length...
I know i can iterate through loop...
but i want to know if 1 line solution is there!!!
Update: I didn't want it to be skill test or spoon feeding. I had written this
for getting unique, wanted to merge with >4 chars
...that's y put the question
sub { @unique{ @words} = 1; @u_words = keys %unique;
Raghu

Replies are listed 'Best First'.
Re: Fast way - get array elements > 4 chars
by ikegami (Patriarch) on Mar 23, 2009 at 14:59 UTC
    my %seen; my @long = grep length>4 && !$seen{$_}++, @array;
Re: Fast way - get array elements > 4 chars
by Limbic~Region (Chancellor) on Mar 23, 2009 at 15:00 UTC
    imrags,
    I am confused. Are you looking for a fast way or are you looking for a way to write unmaintainable code that fits on 1 line? It is a huge mistake to think less code necessarily means faster.

    You might want (untested):

    my %uniq = map {$_ => $_} grep {length $_ > 4} @website; @website = grep defined, @uniq{@website};

    Cheers - L~R

Re: Fast way - get array elements > 4 chars
by ikegami (Patriarch) on Mar 23, 2009 at 17:19 UTC

    I didn't want it to be skill test

    my @uniq = grep !$seen{$_}++, @words;
    preserves order whereas
    @seen{@words} = (); my @uniq = keys %seen;
    doesn't. It's a well known idiom, not a "skill test". It's even listed in the answer to perldoc -q unique. (See perlfaq4)

    wanted to merge with >4 chars

    grep length>4, LIST will filter out all items except those with >4 chars, so you end up with

    my @long = grep !$seen{$_}++, grep length>4, @words;

    or you can combine the two grep calls into one

    my @long = grep length>4 && !$seen{$_}++, @words;
Re: Fast way - get array elements > 4 chars
by sweetblood (Prior) on Mar 23, 2009 at 15:00 UTC
    What have you tried? Also why the 1 line requirement, pretty much any solution 1 line or not will result in looping (iterating) through the array.

    Sweetblood

Re: Fast way - get array elements > 4 chars
by marto (Cardinal) on Mar 23, 2009 at 15:21 UTC

    "but i want to know if 1 line solution is there"

    Really? So whatever solution you have, make it fit on one line. Since you are asking for some code to do this, I'm guessing you currently have nothing working. Will you remember what one line of code will do in a years time?

    When people ask for one liners, I often wonder why. Sure you could golf and obfu something which spans multiple lines into one line, but you've just mad it less readable (and arguably less maintainable) for the next person who has to work with your code.

    I'm still not exactly sure what your question is, do you have HTML you wish to work with? If so are you using any modules for parsing the HTML source? If so is the module source one line long? :P

    Martin

      One liners are great for command line magic. What sed and awk were used for (and still are, I guess).

        Oh I agree, however often when I see someone ask for a one liner in context of a script it sets of an alarm bell. For example, here the OP has not posted any code they've attempted to use to solve the problem, and to be honest, I'm not 100% sure what the actual question being asked is.

        My point being that in circumstances such as this giving someone the answer may be counter productive, since they've been given the solution they asked for, and the script 'works' they may not learn what the code they've been given does, so there is a good chance it will remain undocumented, and perhaps forgotten in the mists of time.

        My issue is not with one liners per se, but consider the following old adage:

        Give someone a fish and they can eat for a day. Teach someone to fish and they can provide their own meals, and in time, teach others :)

        Thanks

        Martin

      I know marto why i need 1 line...
      Not necessarily to maintain it for sure! :)
      Thx for your replies , everyone! :)
      Raghu

        you know why it is yet if we know what it is we help you help yourself

        Bad attempt at my first kaiku. For some reason your reply looked like a haiku to me. lol


        ___________
        Eric Hodges
Re: Fast way - get array elements > 4 chars
by CountZero (Bishop) on Mar 23, 2009 at 15:38 UTC
    I want to know how to extract unique elements in the array

    Do you mean that you only want to handle elements which appear only once in the array or that you want to handle all elements (but skip over duplicates)?

    A solution for skipping over duplicates could be:

    use strict; use warnings; use List::MoreUtils qw/uniq/; my @array = qw/Returns a new list by stripping duplicate values in LIS +T The order of elements in the returned list is the same as in LIST I +n scalar context returns the number of unique elements in LIST/; my @drop_duplicates = uniq grep {length > 4} @array; { local $, = "\n"; print @drop_duplicates;}
    And to extract elements that appear only once:
    use strict; use warnings; my @array = qw/Returns a new list by stripping duplicate values in LIS +T The order of elements in the returned list is the same as in LIST I +n scalar context returns the number of unique elements in LIST/; my %seen; my @only_once = grep {$seen{$_} == 1 } map {$seen{$_}++; $_} grep {len +gth > 4} @array; { local $, = "\n"; print @only_once;}
    Update: added some code examples.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Update: Nevermind, that was your intention. Sorry, I guess I didn't read your whole post.

      The latter doesn't work. You seem to be expecting lazy evaluation, but map processes the entire list before grep is called.

      $ perl -le'print grep { $seen{$_} == 1 } map { $seen{$_}++; $_ } qw( a + b a c );' bc

      Fix:

      grep { ++$seen{$_} == 1 } grep { !$seen{$_}++ }
Re: Fast way - get array elements > 4 chars
by Bloodnok (Vicar) on Mar 23, 2009 at 15:10 UTC
    You mean aside from something like i.e. untested, ...
    %res = ( map { ( $_ => undef ) } grep length > 4, <DATA> ), warn keys +%res;
    or some such??

    I'm sure something like

    warn keys %{ ( map { ( $_ => undef ) } grep length > 4, <DATA> ) };
    should work, but I don't seem to have ever been able to manage it ... ah well, just goes to show how little I know and thus shouldn't come as too great a surprise :D

    update

    Just noticed the length is (was) wrong in my original reply ?

    A user level that continues to overstate my experience :-))
Re: Fast way - get array elements > 4 chars
by rovf (Priest) on Mar 23, 2009 at 15:06 UTC
    i want to know if 1 line solution is there!!!

    I think, you can write *every* Perl program in one line. At least I am not aware about a line length limit in Perl ;-)

    -- 
    Ronald Fischer <ynnor@mm.st>
Re: Fast way - get array elements > 4 chars
by pat_mc (Pilgrim) on Mar 23, 2009 at 21:59 UTC
    As perusual, ikegami has provided a profound solution to the problem which makes further comments superfluous - or plainly embarrassing. I still venture to contribute my humble solution, not because I think it is better but because it takes another line of attack to the problem.

    How about:
    my @array = ( 12, 123456, 134, 3, 45678901, 55555, 3434, 1122334455 ); my @long = ( join " ", @array ) =~ /[^ ]{5,}/g; print join "\n", @long;

    This will return:
    123456 45678901 55555 1122334455
    Is this what you were after? As for performance, I have no idea how this compares to ikegami's solution. Any insights on this?

    Cheers -

    Pat