Forum Moderators: coopster & phranque

Message Too Old, No Replies

create a list by selected field

oh sure - it's easy for you to say

         

idiotgirl

3:30 pm on Jan 21, 2002 (gmt 0)

10+ Year Member Top Contributors Of The Month



I'm stuck. Again. (I feel guilty - if anyone of a coding mentality has a question about graphics feel free to ask away...)

Here's the scenario simplified. Data is stored in a (rather unorderly) fashion like so, but with lot more data fields than what I'm using here:

name:pete¦favcolor:blue¦uniqueid:567¦age:20 
name:ruth¦favcolor:red¦uniqueid:688¦age:50
name:joe¦favcolor:blue¦uniqueid:99¦age:25

Usually, these records are sorted and printed by their unique id. Piece of cake. But now I need it to read from the data file and print like so:

red 
ruth is 50

blue 
pete is 20
joe is 25

doing a foreach by, say, the favcolor field.

Hope that makes sense.

First right answer gets a free Photoshop tutorial.

gethan

4:18 pm on Jan 21, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



[perl]#!perl -w
use Data::Dumper;
use strict;

open DATA, "data.txt";
my @a = <DATA>;
close DATA;
my ($l, %stuff, %index);

foreach $l (@a) {
chomp $l;
my (%data) = split(/[¦:]/, $l);

print Dumper(\%data) ."\n\n";

$stuff{$data{'uniqueid'}} = \%data;
foreach (keys %data) {
my $ref = $index{$_}¦¦[];
my @t = @$ref;
push(@t,$data{$_});
$index{$_} = \@t;
}
}

print Dumper(\%stuff) ."\n\n";
print Dumper(\%index) ."\n\n";

# nice little structure can now be manipulated. eg.
my $color;
my $colref = $index{'favcolor'};
foreach $color (@$colref) {
print "\nColor $color\n";
foreach (values %stuff) {
my %p = %$_;
print "\t$p{'name'} is $p{'age'}\n" if $p{'favcolor'} eq $color;
}
}[/perl]

Remember the ¦ caveat ... in the split and ¦¦ - delete and retype to make work.

Probably a few performance enhancements that could be added in ... lots of looping in loops ;) If there are a huge number of vals, then the index could be extended to be a hash of hashes, eg.

favcolor => red => (323,44,32)
favcolor => blue => (3,23)

etc.

OK .. erm back to my work again.

idiotgirl

4:34 pm on Jan 21, 2002 (gmt 0)

10+ Year Member Top Contributors Of The Month



gethan - you're on your way back to work and I'm just getting ready to take a nap. hmmm,

Originally, this was called as an SSI, with the db to be used as the query:

$query = $ENV{QUERY_STRING}; 
print "Content-Type: text/html\n\n";
open (LOGFILE,"<$query\.db");
@log=<LOGFILE>;
close (LOGFILE);
print "<TABLE BORDER=\"0\" cellpadding=\"0\" cellspacing=\"4\" width=\"100%\">\n";

foreach $line (@log) {
@fieldsa = split(/\¦/, $line);
foreach $ize (@fieldsa) {
@izetomb = split(/\:/, $ize);
$ahash{$izetomb[0]} = $izetomb[1];
}

print "<tr><td>$ahash{'name'} $ahash{'favcolor'}</td></tr>\n";

... and whatever else. Would this (your snippet) work as an SSI with an html embedded query calling the logfile to be parsed?

I know. idiotgirl.

gethan

4:54 pm on Jan 21, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



If you drop out all the Data::Dumper's I don't see why not. Never really bothered with SSI (I got mod_rewrite ;p)

Just drop the snippet at the point where you have an array for each line of gumph... and switch to doing html prints. I guess give it ago ;)

gethan

5:07 pm on Jan 21, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



With better indexes... if your doing something like this below it could be done more efficiently, but this the most generic way of doing something like this (I can think of)... I have a few apps that will be using something similar ... config type stuff.

Also the dereferencing and referencing of vars could be done in fewer lines... but I think its confusing enough already.

[perl]#!perl -w
use Data::Dumper;
use strict;

open DATA, "data.txt";
my @a = <DATA>;
close DATA;
my ($l, %stuff, %index);

foreach $l (@a) {
chomp $l;
my (%data) = split(/[¦:]/, $l);

print Dumper(\%data) ."\n\n";

$stuff{$data{'uniqueid'}} = \%data;
foreach (keys %data) {
my $ref1 = $index{$_}¦¦+{};
my %t = %$ref1;
my $ref2 = $t{$data{$_}}¦¦[];
my @t = @$ref2;
push(@t,$data{'uniqueid'});
$t{$data{$_}} = \@t;
$index{$_} = \%t;
}
}

print Dumper(\%stuff) ."\n\n";
print Dumper(\%index) ."\n\n";

# nice little structure can now be manipulated. eg.
my $color;
my $colref = $index{'favcolor'};
my %colors = %$colref;

foreach $color (keys %colors) {

my $t = $colors{$color};
my @t = @$t;

print "\nColor $color\n";
foreach (@t) {
my $r = $stuff{$_};
my %p = %$r;
print "\t$p{'name'} is $p{'age'}\n";
}
}[/perl]

idiotgirl

1:19 am on Jan 22, 2002 (gmt 0)

10+ Year Member Top Contributors Of The Month



gethan-

I tested this simple - using my test lines as data.txt, taking out the Data::Dumper, strict, and going vanilla.

I think the initial:

my (%data) = split(/[¦:]/, $line); 

is causing errors.

I ran it both ways - with and without Data::Dumper, and I kept getting an error returned where the split was. I did change to pipes.


open DATA, "data.txt";
my @a = <DATA>;
close DATA;
my ($line, %stuff, %index);
foreach $line (@a) {
    chomp $line;
    my (%data) = split(/[¦:]/, $line);
   
    $stuff{$data{'uniqueid'}} = \%data;
    foreach (keys %data) {
        my $ref1 = $index{$_}¦¦+{};
        my %t = %$ref1;
        my $ref2 = $t{$data{$_}}¦¦[];
        my @t = @$ref2;
        push(@t,$data{'uniqueid'});
        $t{$data{$_}} = \@t;
        $index{$_} = \%t;
    }
}

my $color;
my $colref = $index{'favcolor'};
my %colors = %$colref;
foreach $color (keys %colors) {
        
    my $t = $colors{$color};
    my @t = @$t;
    
    print "\nColor $color\n";
    foreach (@t) {
        my $r = $stuff{$_};
        my %p = %$r;
        print "\t$p{'name'} is $p{'age'}\n";
    }
}

amoore

3:44 am on Jan 22, 2002 (gmt 0)

10+ Year Member



well, without knowing what the error is, it's a hard one to troubleshoot, but can I make a suggestion nonetheless?

I would reccommed using a loop like:

whie (<DATA>) {
# do stuff...
}

to walk through your file so you don't have to slurp the entire file into memory at the beginning.

You may also want to check the result of your call to "open"
open DATA, "data.txt" or die "cannot open data.txt. $!";
or something.

gethan

4:48 pm on Jan 22, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Stumped without out the error msg also ... worked fine for me honest ;)

Did it work as a command line app? Or did this problem only occur with SSI?

The Data::Dumper call are there so you can see what's built and then how to use it in more general situations.

amoore: good call on both points.