Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Module for making english lists?

by markjugg (Curate)
on Aug 25, 2008 at 21:16 UTC ( [id://706786]=perlquestion: print w/replies, xml ) Need Help??

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

Hello,

I'm looking for a module recommendation for the task of a spelling out a list as if it were an English phrase. It would compute the following, given phases of "a", "b" and "c:

a -> "a" a,b -> "a and b" a,b,c -> "a, b, and c" a,b,c,d -> "a, b, c, and d"
..and so forth. It wouldn't be so hard to write such a function, but it seems likely to already exist. Thanks!

Replies are listed 'Best First'.
Re: Module for making english lists?
by ysth (Canon) on Aug 26, 2008 at 00:48 UTC
      Conjunction Junction, what's your function?
      Thanks to everyone for the suggestions. I think I'll go with Linqua::Conjunction since it is already packaged up with docs and tests, and has some other options like using "or" instead of "and".
Re: Module for making english lists?
by moritz (Cardinal) on Aug 25, 2008 at 21:27 UTC
    Now it's written:
    #!/usr/bin/perl use strict; use warnings; my @list = ( [qw(a)], [qw(a b)], [qw(a b c)], ); for (@list){ print join_english(@$_), $/; } sub join_english { return $_[0] if @_ < 2; my $last = pop @_; return join(', ', @_), ' and ' . $last; }

    I don't know if that's worth a module, if you think so, you could upload it to CPAN as Lingua::List::English or something. I searched for lingua list and found nothing, but maybe I overlooked something.

Re: Module for making english lists?
by kyle (Abbot) on Aug 25, 2008 at 21:26 UTC

    Yeah, pretty easy to write...

    sub mkenglish { die 'arg required' if ! @_; if ( 1 == scalar @_ ) { return @_; } elsif ( 2 == scalar @_ ) { return join ' and ', @_; } else { my $last = pop @_; my $list = join ', ', @_; return "$list, and $last"; } }

    You might also be interested in reading about the Serial comma.

Re: Module for making english lists?
by Your Mother (Archbishop) on Aug 25, 2008 at 22:04 UTC

    How about serial comma function? :) Short enough to reproduce here. I use it in my TT2 filters.

    sub serial { join(', ', @_[0..$#_-1]) . (@_>2 ? ',':'' ) . (@_>1 ? (' and ' . $_[-1]) : $_[-1]); }
Re: Module for making english lists?
by AnomalousMonk (Archbishop) on Aug 26, 2008 at 00:02 UTC
    FWIW:

    perl -wMstrict -le "sub standard_commas { return @_ == 0 ? '' : @_ == 1 ? qq($_[0]) : @_ == 2 ? qq($_[0] and $_[1]) : join ', ', shift, standard_commas(@_) } sub oxford_commas { return @_ <= 2 ? standard_commas(@_) : @_ == 3 ? qq($_[0], $_[1], and $_[2]) : join ', ', shift, oxford_commas(@_) } for (@ARGV) { my @words = split; print qq(\nfor words: @words); print 'standard commas: ', standard_commas(@words); print 'oxford commas: ', oxford_commas (@words); } " "" "a" "a b" "a b c" "a b c d" "a b c d e" "a c d e f" for words: standard commas: oxford commas: for words: a standard commas: a oxford commas: a for words: a b standard commas: a and b oxford commas: a and b for words: a b c standard commas: a, b and c oxford commas: a, b, and c for words: a b c d standard commas: a, b, c and d oxford commas: a, b, c, and d for words: a b c d e standard commas: a, b, c, d and e oxford commas: a, b, c, d, and e for words: a c d e f standard commas: a, c, d, e and f oxford commas: a, c, d, e, and f
      Or, shorter, sweeter and non-recursive (and kind of a restatement of Your Mother's contribution):

      perl -wMstrict -le "sub standard_commas { return @_ == 0 ? '' : @_ == 1 ? qq{$_[0]} : join q{, }, @_[0 .. $#_ - 2], qq{$_[-2] and $_[-1]} } sub oxford_commas { return @_ < 3 ? standard_commas(@_) : join q{, }, @_[0 .. $#_ - 1], qq{and $_[-1]} } for (@ARGV) { my @words = split; print qq(\nfor words: @words); print 'standard commas: ', standard_commas(@words); print ' oxford commas: ', oxford_commas(@words); } " "" "a" "a b" "a b c" "a b c d" "a b c d e" for words: standard commas: oxford commas: for words: a standard commas: a oxford commas: a for words: a b standard commas: a and b oxford commas: a and b for words: a b c standard commas: a, b and c oxford commas: a, b, and c for words: a b c d standard commas: a, b, c and d oxford commas: a, b, c, and d for words: a b c d e standard commas: a, b, c, d and e oxford commas: a, b, c, d, and e
        And, since I don't seem to be able to let this go, still shorter and sweeter:

        sub standard_commas { return join q{, }, @_ < 2 ? @_ : (@_[0 .. $#_ - 2], qq{$_[-2] and $_[-1]}) } sub oxford_commas { return join q{, }, @_ < 3 ? goto &standard_commas : (@_[0 .. $#_ - 1], qq{and $_[-1]}) }
        Tested. The output, which I won't inflict upon you again, is the same.
Re: Module for making english lists?
by didess (Sexton) on Aug 25, 2008 at 21:52 UTC
    Hello, don't you think this is enough:
    #!/usr/bin/perl $S = "a , b, c,d"; sub modif { my ($S) = @_; $S =~ s/(.*),/$1 and /; $S =~ s/\s*,\s*/, /g; return $S; } print "\$S=$S ==> ". modif($S) . "\n";
    in case of an array (or list), join it with commas before:
    @Arr = (1 , 2, 3,4); print "Array = ". modif(join(',',@Arr)) . "\n";
    I don't think is worth a module! Hope it helps !
Re: Module for making english lists?
by Fletch (Bishop) on Aug 26, 2008 at 00:25 UTC

    Probably not the module you're looking for, but then again you're not going to be able to turn any of the others in for your homework either . . .

    module Main where eng_commafy :: (Show a) => [a] -> String eng_commafy x | length x > 2 = foldl1 (commacat) init_as_show ++ ", a +nd " ++ last_show where commacat x y = x ++ ", " ++ y init_as_show = map (show) (init x) last_show = show (last x) eng_commafy x | length x == 2 = (show (head x)) ++ " and " ++ (show (l +ast x)) eng_commafy x | length x == 1 = show (head x) eng_commafy [] = "" main = do putStrLn (eng_commafy [1..10]) putStrLn (eng_commafy [1,2]) putStrLn (eng_commafy [1])

    (Yeah, my Haskell's terrible . . . :)

    Update: Actually looking at the OP's posting history this is probably not homework. But it's still trivial and probably not past the threshold of "should be stuck in a module" on its own.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: Module for making english lists?
by johndageek (Hermit) on Aug 26, 2008 at 22:03 UTC
    I dunno, try this just for fun

    #!/usr/bin/perl @str = ("a,b,c,d,e", "a", "a,b", "a,b,c"); foreach $x (@str){ $x =~ s/\,(\w+)$/ and $1/; print "$x\n"; }

    Enjoy!
    Dageek

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (2)
As of 2024-04-26 04:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found