Beefy Boxes and Bandwidth Generously Provided by pair Networks BBQ
Pathologically Eclectic Rubbish Lister

removing a sublist

by Datz_cozee75 (Acolyte)
on Apr 20, 2012 at 21:48 UTC ( #966275=perlquestion: print w/ replies, xml ) Need Help??
Datz_cozee75 has asked for the wisdom of the Perl Monks concerning the following question:

When I study a syntax, I try to use it for any odd task that turns up. We have a contest for a club of sorts where the winner gets a prize of value $25 or so, but the idea is to foster participation. Hence, we don't want perpetual winners or the winner to be the person who sits at his computer all day, so we're choosing a random correct answer as opposed to the first.

Where I'm stuck now is making a composite of the those who answer correctly less those who have already won. I looked for examples in the books I have and couldn't find one. If I were to proceed in the manner of the syntaxes I've studied before, I would loop through indices, making exhaustive comparisons. What is the perl way to remove a sublist from another list

$ perl 7246281254938614119473194136957146644855362901505395617562308444592359 +441659779924940736387588266118823158415004985978328481067994672839164 +223678436588869 2 $ cat #!/usr/bin/perl -w use strict; use feature ':5.10'; use Crypt::Random qw( makerandom ); my $r = makerandom ( Size => 512, Strength => 1 ); print "$r\n"; srand($r); my @winners=("ruth","sheila"); my @correct=("ruth","martin","dee","zack"); my @composite = @correct - @winners; print "@composite \n"; $

Thanks in advance,

Comment on removing a sublist
Download Code
Re: removing a sublist
by Riales (Hermit) on Apr 20, 2012 at 21:57 UTC
    my @no_prev_winners = grep { my $correct = $_; !grep { $_ eq $correct } @winners } @correct;
Re: removing a sublist
by Skeeve (Vicar) on Apr 20, 2012 at 22:21 UTC

    I always use a hash for this:

    my @winners=("ruth","sheila"); my @correct=("ruth","martin","dee","zack"); my %correct; @correct{@correct}= (); delete @correct{@winners}; print join(' ',keys %correct),"\n";


      Alright, Skeeve, that's exactly the way I was headed, but it doesn't take me very long before I'm confounded by it. I find myself always wanting to revert to indices and crush it with brute force exhaustion like a numerical integration in fortran. I rarely find myself disappointed when I trust perl syntax.

      Am I correct to think that the keys do not have to be unique? In my mind, the keys would represent the number of times a person has won. Stan won twice and dan won once. How do I marry @frequency to @correct in the script below?

      $ perl fan dango 4 4 2 1 $ cat #!/usr/bin/perl -w use strict; use 5.10.0; use Crypt::Random qw( makerandom ); # initialize pseudorandoms my $r = makerandom( Size => 512, Strength => 1 ); # print "$r\n"; srand($r); #populate lists my @winners = qw/stan dan/; my @winner_copy = @winners; my @correct = qw/stan dan fan dango/; my @correct_copy = @correct; #populate hash my %correct; @correct{@correct} = (); delete @correct{@winners}; print join( ' ', keys %correct ), "\n"; my $count = scalar(@correct); print "$count\n"; my @new_list = @correct; $count = scalar(@new_list); print "$count\n"; # if ( scalar(@correct) eq 0 ) my @frequency = (2, 1); # --@frequency; that didn't work print "@frequency", "\n"; # decrement frequency # does anyone with a key value of zero have a correct response yet? # if yes, you have a winner; if not then test whether there was a corr +ect response among those with positive keys. # if no one correct among them, then there was no correct response, be +cause that partitions the sets. $

      I tried to map out in pseudoscript what I'm doing here. Obviously, I don't have the parts to make a control that works yet, but the contest just started today, so I don't have to have winner until after the time window closes.

      Why does the hash have 4 nodes after 2 have been deleted?

      How do I decrement the keys of a hash?

Re: removing a sublist
by Kenosis (Priest) on Apr 20, 2012 at 23:08 UTC

    Good solutions have been provided. The following includes randomly selecting a new winner:

    map{$winners_hash{$_}++}@winners; @new_winners = grep{!$winners_hash{$_}}@correct; $the_winner = $new_winners[int(rand($#new_winners+1))];

    Unless you're using an old version of perl, rand automatically calls srand.

    Hope this helps!

Re: removing a sublist
by eyepopslikeamosquito (Canon) on Apr 20, 2012 at 23:54 UTC

    See perlfaq4 (arrays section) and Perl Cookbook, recipe 4.8 "Finding elements in one array but not another".

    I would do it like this:

    my @winners = ( "ruth", "sheila" ); my @correct = ( "ruth", "martin", "dee", "zack" ); # Build lookup table of winners my %in_winners = map { $_ => 1 } @winners; # Find items that are in @correct but not in @winners my @correct_only = grep { not $in_winners{$_} } @correct;

Re: removing a sublist
by toolic (Chancellor) on Apr 21, 2012 at 02:00 UTC
    use warnings; use strict; use Acme::Tools qw(minus); use Data::Dumper; my @winners=("ruth","sheila"); my @correct=("ruth","martin","dee","zack"); my @composite = minus(\@correct, \@winners); print Dumper(\@composite); __END__ $VAR1 = [ 'martin', 'dee', 'zack' ];

    Also, qw is a convenient list constructor.

Re: removing a sublist
by Cristoforo (Chaplain) on Apr 21, 2012 at 15:28 UTC
    List::Compare will also solve this problem.
    #!/usr/bin/perl use strict; use warnings; use 5.014; use List::Compare; my @winners=("ruth","sheila"); my @correct=("ruth","martin","dee","zack"); my $lc = List::Compare->new(\@winners, \@correct); my @composite = $lc->get_Ronly; print "@composite\n";
    dee martin zack


Log In?

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

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (11)
As of 2014-04-19 08:04 GMT
Find Nodes?
    Voting Booth?

    April first is:

    Results (478 votes), past polls