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

Hi Monks , Can you see the problem with my code? I am comparing two files and printing the different out.
scheduled contact.txt --------- ----------- Sam 5:00 sam 324-232-3333 scott 4:45 Joe 235-309-3333 saleem 5:00 Saleem 323-747-0000 Ken 7:00 Ken 764-636-9999 Ken 8:00 open (FILE1, '<', 'scheduled') or die "Unable to open file1.txt for re +ading : $!"; open (CONTACT, '<', 'contact.txt' ) or die "Unable to open contatct.tx +t: $!"; while (my $list = <CONTACT>) { chomp $list; my @names = split(/ /, $list); my $name = ($names[0]); open (FILE3, '>>', 'Available') or die "Unable to open Tuesday.rep for + writing : $!"; while (my $line = <FILE1>) { chomp $line; unless ($line =~ m/^$name/) { #print FILE3 "$list\n"; print " the line is $list\n"; print " the sched is $line\n"; } } }
what I am doing is trying to print the contact of the person who is not in the schedul , in my example I will need to only print  Joe 235-309-3333 My code is doing it wrong and also check for ken who is schedul twice , two times which I dont' want . If the person is schedul then I don't need to print it . Can you help?

Replies are listed 'Best First'.
Re: not able to compare files
by NetWallah (Canon) on Mar 12, 2004 at 05:12 UTC
    You have some basic program design problems here.

    You are attempting to read the entire file FILE1 for each record of CONTACT. Was that you intention ?

    To match "sam" with "Sam", you need to ignore case. The syntax for that would be m/^$name/i. the "i" ignores case.

    Depending on how large these files are, and whether or not they are sorted, there are different approaches to solving the problem. Typically, one of the files would be read completely into memory - in this case, store the info in a hash, that you can look up quickly.

    Try re-writing using these suggestions, and we can help you get through the next step.

      Ok, first off, you don't want a while loop inside of another while loop for this problem. I'd start by loading all of your people on the schedule into a hash:
      my %contacts; while (<FILE1>){ my ($person, $trash) = split(/\s/, $_, 2); $contacts{$person} = 0; }
      Next, read in your contacts and determine if they exist in your schedule:
      while (<CONTACT>){ my ($person, $extra) = split(/\s/, $_, 2); print FILE3 "$person\t$extra" unless exists $contacts{$person}; }
      Of course, if somebody appears twice in your contacts file, they'll print out twice too. While you're at it, be sure to use strict and warnings and be nice, remember to close your filehandles. You don't need to chomp() anything since you're going to want the carriage return when you print to file.

      - - arden.

Re: not able to compare files
by nandeya (Monk) on Mar 12, 2004 at 05:34 UTC
    Probably more efficient ways to do, but wanted to blow a minute or two before I went to bed.

    #!perl use strict; my (%schds, %conts, %in_conts_not_schds); open( MILF, "C:/junk/scheduled.txt" ) or die "Can't open scheduled.txt +\n"; while( <MILF> ) { split(/\s+/,$_); $schds{lc(@_[0])}=1; } close MILF; open( CONT, "C:/junk/contact.txt" ) or die "Can't open contact.txt\n"; while( <CONT> ) { split(/\s+/,$_); $conts{lc(@_[0])}=[@_[0], @_[1]]; #Retain case of name } close CONT; foreach (keys %conts) { unless (exists $schds{$_}) { $in_conts_not_schds{$conts{$_}->[0]} = $conts{$_}->[1]; } } foreach (sort keys %in_conts_not_schds) { print "$_ $in_conts_not_schds{$_}\n"; } ___END... FILES FOLLOW____ scheduled.txt Sam 5:00 scott 4:45 saleem 5:00 Ken 7:00 Ken 8:00 contact.txt sam 324-232-3333 Joe 235-309-3333 Saleem 323-747-0000 Ken 764-636-9999

Re: not able to compare files
by pbeckingham (Parson) on Mar 12, 2004 at 05:30 UTC

    Please use -w and strict, I believe it will be of great benefit to you as you rewrite this - and you do need to rewrite this. If you also indent your code to represent the scoping, your code will be much clearer to you and us.

    If you were to read the scheduled file, and extract the names with something like this:

    while (<SCHEDULED>) { my ($who) = /^(.*?)\s/; ... }
    then you have the basis of what you need.

    You may also want to convert all names to lower case for simpler comparison.