Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

sort array

by welle (Beadle)
on Apr 30, 2012 at 18:37 UTC ( #968124=perlquestion: print w/ replies, xml ) Need Help??
welle has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

I need your help. I have an array containing sentences. I want to order the sentences according to a given word (i.e. the third from the left).

I am a nice boy You are a nice boy They are not good at all

What I found is the following (adapting it from Lingua::Concordancer):

sub order_line{ my @sorted_lines; foreach ( sort { _by_left( $a, $b ) } @lines ) { push @sorted_line +s, $_ } print @sorted_lines; } sub _by_left { my ( $a, $b ) = @_; return lc( _on_left( $a )) cmp lc( _on_left( $b )); } sub _on_left { my ( $s ) = @_; my @words = split( /\s+/); my $word_level=3; return $words[ scalar( @words ) - $word_level ]; }

Of course it doesn't work...

Comment on sort array
Download Code
Re: sort array
by Cristoforo (Deacon) on Apr 30, 2012 at 19:26 UTC
    Your subroutine may work with a few changes. However, I rewrote it to try a simpler approach. Here is a sample program you can run.

    #!/usr/bin/perl use strict; use warnings; my @lines = split /\n/, <<EOF; I need your help. I have an array containing sentences. I want to order the sentences according to a given word I am a nice boy You are a nice boy They are not good at all EOF print "$_\n" for order_line(@lines); sub order_line { return sort by_3d_word_from_right @_; } sub by_3d_word_from_right { { lc((split ' ', $a)[-3]) cmp lc((split ' ', $b)[-3]) } }
Re: sort array
by jwkrahn (Monsignor) on Apr 30, 2012 at 20:00 UTC
    sub _on_left { my ( $s ) = @_; my @words = split( /\s+/); my $word_level=3; return $words[ scalar( @words ) - $word_level ]; }

    You say you want the third word from the left but you are accessing the third word from the right.    $words[ scalar( @words ) - $word_level ] should be $words[ $word_level - 1 ].

    But you are not actually getting a word because split( /\s+/) is short for split( /\s+/, $_) and you don't have a value in $_ to split on.

    So you want something like this:

    sub _on_left { my ( $s ) = @_; my @words = split ' ', $s; my $word_level = 3; return $words[ $word_level - 1 ]; }


    sub order_line{ my @sorted_lines; foreach ( sort { _by_left( $a, $b ) } @lines ) { push @sorted_line +s, $_ } print @sorted_lines; } sub _by_left { my ( $a, $b ) = @_; return lc( _on_left( $a )) cmp lc( _on_left( $b )); }

    You don't need a foreach loop, you can just do:

    sub order_line{ my @sorted_lines = sort { _by_left( $a, $b ) } @lines; print @sorted_lines; }

    And instead of calling a subroutine in the sort block you could just use the subroutine name:

    sub order_line{ my @sorted_lines = sort _by_left @lines; print @sorted_lines; } sub _by_left { return lc( _on_left( $a )) cmp lc( _on_left( $b )); }
Re: sort array
by Kenosis (Priest) on Apr 30, 2012 at 20:27 UTC

    Another option (Schwartzian transform):

    map{print "$_->[0]\n"} sort {$a->[1] cmp $b->[1]} map{[$_, (split)[2]]} @lines;

    Sorts on third word from the left. Replace [2] with [-3] after (split) to sort on third word from the right.

    Hope this helps!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://968124]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (15)
As of 2014-12-18 17:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (59 votes), past polls