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

ok, what i'm trying to do is, eventually, after everything is done, print the line that the results came from with the results.

first, i think there's an easier way to do this as i'm sorta tieing my brain in knots thinking about what array of what hash is going where. second, if this is the best way to do this, how do i print the string and not the array value (what it seems to be printing) in the final loop?

#!/usr/bin/perl use DBI; my $searcher = "owner.manager, owner.owner, owner.man"; my $dbh = DBI->connect('DBI:mysql:db;host=localhost', 'user', 'pass') or die "Database connection: $!"; open( FILE, "< $ARGV[0]" ); my %uword = (); my %seen = (); my $count = 0; my @data; my $key; my $i = 0; while ( <FILE> ) { my $line = $_; chomp ($line); my @word = split / /, $line; $count = 0; while ( $word[ $count ] ) { $word[ $count ] =~ tr/^[\-a-zA-Z]//; $word[ $count ] =~ s/\'/\\\'/g; $count++; } foreach my $string ( @word ) { if ( $uwordi{ $string }[ 0 ] == 1 ) { push @{ $uword{ $string } }, $line; next; } $uword{ $string }[ 0 ] = 1; push @{ $uword{ $string } }, $line; } } $count = 0; while ( $key = keys %uword ) { my ( $imo, $owner, $manown, $manager ); my $sstring = $uword{ $key }; my $select = qq/SELECT $searcher /; my $from = qq/FROM owner, data /; my $where = qq/WHERE MATCH( $searcher ) AGAINST('+ +$sstring' IN BOOLEAN MODE) /; my $join = qq/AND owner.num = data.num/; my $query = $select . $from . $where . $join; print "SQL: $query\n"; my $sth = $dbh->prepare( $query ); $sth->execute; $sth->bind_columns( \$manager, \$owner, \$man ); while ( $sth->fetch ) { if ( defined( $owner ) ) { $data[$count] = $owner; $count++; } if ( defined( $man ) ) { $data[$count] = $manown; $count++; } if ( defined( $manager ) ) { $data[$count] = $manager; $count++ } } foreach my $string ( @data ) { next if !defined ($string); if ( $seen{ $string }[ 0 ] == 1 ) { for my $value (1 .. $#{ $uword{ $string } } ) +{ push @{ $seen{ $string } }, $uword{ $s +tring }[ $value ]; } next; } $seen{ $string }[ 0 ] = 1; for my $value (1 .. $#{ $uword{ $string } } ) { push @{ $seen{ $string } }, $uword{ $string }[ + $value ]; } } } $dbh->disconnect;

Replies are listed 'Best First'.
Re: keeping context in a loop
by toolic (Bishop) on Oct 25, 2010 at 18:19 UTC
    use warnings and strict. If I turn on warnings, I get this message:
    Name "main::uwordi" used only once: possible typo at...

    Fix that first, then if you still have problems, try to reduce your code to something we can run -- without reliance on external files or databases.

Re: keeping context in a loop
by jwkrahn (Abbot) on Oct 26, 2010 at 00:29 UTC
    #!/usr/bin/perl use DBI;

    You should also enable warnings and strictures to let Perl help you find mistakes.

    #!/usr/bin/perl use warnings; use strict; use DBI;


    open( FILE, "< $ARGV[0]" );

    You should always verify that the file opened correctly.

    open FILE, '<', $ARGV[ 0 ] or die "Cannot open '$ARGV[ 0 ]' $!";


    while ( <FILE> ) { my $line = $_; chomp ($line); my @word = split / /, $line;

    Or simply:

    while ( my $line = <FILE> ) { chomp $line; my @word = split ' ', $line;


    $count = 0; while ( $word[ $count ] ) { $word[ $count ] =~ tr/^[\-a-zA-Z]//; $word[ $count ] =~ s/\'/\\\'/g; $count++; }

    That is usually written as:

    for ( @word ) { tr/^[\-a-zA-Z]//; s/\'/\\\'/g; }

    But tr/^[\-a-zA-Z]// doesn't do anything in this context so why is it there?



    while ( $key = keys %uword ) {

    That looks like you should be using each instead of keys as that produces an infinite loop.



Re: keeping context in a loop
by ig (Vicar) on Oct 26, 2010 at 08:41 UTC
    how do i print the string and not the array value

    I am guessing that you are seeing something like ARRAY(0x9b31880) in your SQL query text. This would be because $uword{ $key } is an array reference. If you want to see the text of all the elements in the referenced array, you could use something like join(' ', @{ $uword{ $key } } ). This may not be what you want either, but at least you would be seeing text.

    If I have guessed incorrectly, you could post a sample of the output you are getting and describe what is wrong with it, and also post an example of what you want the output to look like.

    You might find brian's Guide to Solving Any Perl Problem helpful. There is some very good advice there that would help you investigate and solve your problems.

    You might also consider using $dbh->quote() to quote the strings you are inserting into your SQL statement.

      You might also consider using $dbh->quote() to quote the strings you are inserting into your SQL statement.

      Even better: Don't quote at all and use placeholders instead, especially when the SQL statement is executed repeatedly. That way, DBI and the database can cache a lot of the work that has to be repeated when not using placeholders. See Re: Counting rows Sqlite, Re^2: Massive Memory Leak, and of course the DBI documentation.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)