Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Advanced Sorting - Quick Question 1

Status
Not open for further replies.

Alphabin

Programmer
Dec 8, 2002
119
CA
Hi,

I have a flat file with the following structure:

Code:
DataTest.txt

210|Roger|Brodie|RB|NY| 
221|Jake|Namol|JK|NY|210
223|Matt|Lamon|MM|NY|221
227|Litia|Lumberg|LM|NY|221
211|Peter|Givens|BV|NY| 
224|Rob|Lumen|RB|NY|211
234|Lopez|Lucas|LL|NY|211

Note:
Field 0 is User ID
Field 5 is Parent USER ID they report to (if applicable)

Now I want to list this data so it would be like this
(Child under Parent which they report to)

- Peter Givens (211)
- Lopez Lucas (234)
- Rob Lumen (224)

- Roger Brodie (210)
- Jake Namol (221)
- Matt Lamon (223)
- Lithia Lumberg (227)

Code I have right now
Code:
open(FILE,"$DataTest.txt");
my @database=<FILE>;
close(FILE);

foreach my $record (@database) {
chop $record;

# Split fields 
my @fields=split(/\|/,$record);
	
push (@groups,[@fields]);
}
	
my $parent_group = "";

foreach my $group (sort { 
if ($a->[0] eq $b->[0]) { $a->[0] cmp $b->[0] } 
else { $a->[1] cmp $b->[1] } } @groups) {
		
	if ($group->[5] ne $parent_group) {
	print "$group->[1] <b>($group->[0])</b><br>\n";
			
	$parent_group = $group->[5];
	}
			
	print "&nbsp;&nbsp; group->[1] <br>\n";
		
	}

Thank you in advance


 
By the way, the code I have right now (posted above) does not produce the right output... (

Duncdude.. need your help.. ;)

 
I modified it a bit.

Code:
while(<DATA>) {
    chomp;
    my ($id,$fname,$lname,$x,$y,$pid)=split(/\|/);
    @{$people{$id}}{'pid', 'fname','lname','x', 'y'} = ($pid, $fname, $lname, $x, $y);
}

my $depth = -1;

for(keys %people){
    print_person($_) unless $people{$_}{'pid'};
}

sub print_person {
    my $id = shift;
    $depth++;
    print "\t" x $depth;
    print join(' ', @{$people{$id}}{'fname', 'lname'}, "($id)"), "\n";
    for( keys %people ){
        print_person($_) if $people{$_}{'pid'} == $id;
    }
    $depth--;
}


__DATA__
210|Roger|Brodie|RB|NY| 
221|Jake|Namol|JK|NY|210
223|Matt|Lamon|MM|NY|221
227|Litia|Lumberg|LM|NY|221
211|Peter|Givens|BV|NY| 
224|Rob|Lumen|RB|NY|211
234|Lopez|Lucas|LL|NY|211

Recursion seemed to be the way to go.

--jim
 
OOOOPS. I was screwing around and left out something important in my cut and paste. Try this instead:
Code:
while(<DATA>) {
    chomp;
    my ($id,$fname,$lname,$x,$y,$pid)=split(/\|/);
    @{$people{$id}}{'pid', 'fname','lname','x', 'y'} = ($pid, $fname, $lname, $x, $y);
}

my $depth = -1;

for(keys %people){
    print_person($_) unless $people{$_}{'pid'} =~ /\d/;
}

sub print_person {
    my $id = shift;
    $depth++;
    print "\t" x $depth;
    print join(' ', @{$people{$id}}{'fname', 'lname'}, "($id)"), "\n";
    for( keys %people ){
        print_person($_) if $people{$_}{'pid'} == $id;
    }
    $depth--;
}


__DATA__
210|Roger|Brodie|RB|NY| 
221|Jake|Namol|JK|NY|210
223|Matt|Lamon|MM|NY|221
227|Litia|Lumberg|LM|NY|221
211|Peter|Givens|BV|NY| 
224|Rob|Lumen|RB|NY|211
234|Lopez|Lucas|LL|NY|211

--jim
 
I appreciate your vote of confidence Alphabin - but I don't think I could have done that... Jim saves the day again!


Kind Regards
Duncan
 
Thank you Coderifous for your help.
Strange thing: I'm not getting any output. It's processing, but I get nothing. Even If I change it to open the flat file instead of <DATA> .

Is it working on your side ?

Thank you

Duncdude: ;) You've helped me so much in the past... Really appreciated.

 
Jim... Just realized something. The coding in your second post is the same as the first one...
 
Alphabin.... look really really close.

The code from my first post outputs nothing.

The code from the second post outputs the sweetness.

Make *SURE* you are using the code from the second post.

The difference is this:
Code:
 =~ /\d/
--jim
 
Weird... Because I'm using the code from your second post and I'm still getting nothing. Also, Perl.exe went to 25 000K after running the script...

 
Ignore my last post Jim
You're work is the sweetness
Thank you very much for your help. It's really appreciated.

You get a BIG STAR !

 
*WHEW* - that's a good thing, because I would have been at a loss if that was the case.

Glad I could help.

--jim
 
This should be my last revision. I like this version a little bit better (very minor change) becuase I avoid using the regex. That was kind of a hack. By using the +0 in the assignment of the $pid, we are forcing the scalar into numerical context, so that if it is a space or an empty string, it is assigned as 0. This will be better for you, and will work as long as you don't have anyone with an ID of 0.
And there is one less print statement.

Code:
while(<DATA>) {
    chomp;
    my ($id,$fname,$lname,$x,$y,$pid)=split(/\|/);
    @{$people{$id}}{'pid', 'fname','lname','x', 'y'} = ([red]$pid+0[/red], $fname, $lname, $x, $y);
}

my $depth = -1;

for(keys %people){
    [red]print_person($_) unless $people{$_}{'pid'};[/red]
}

sub print_person {
    my $id = shift;
    $depth++;
    print "\t" x $depth, join(' ', @{$people{$id}}{'fname', 'lname'}, "($id)"), "\n";
    for( keys %people ){
        print_person($_) if $people{$_}{'pid'} == $id;
    }
    $depth--;
}


__DATA__
210|Roger|Brodie|RB|NY| 
221|Jake|Namol|JK|NY|210
223|Matt|Lamon|MM|NY|221
227|Litia|Lumberg|LM|NY|221
211|Peter|Givens|BV|NY| 
224|Rob|Lumen|RB|NY|211
234|Lopez|Lucas|LL|NY|211

have a nice day. please come again.

--jim
 
Thanks again Jim. Even better

I have one last question for you. I'm trying to sort the list in alphabetical order.

Here's my current code (btw, did small work to output list in HTML)

Code:
#!/usr/bin/perl

print "Content-type: text/html\n\n";

while(<DATA>) {
    chomp;
    my ($id,$fname,$lname,$x,$y,$pid)=split(/\|/);
    @{$people{$id}}{'pid', 'fname','lname','x', 'y'} = ($pid+0, $fname, $lname, $x, $y);
}

my $depth = -1;

[red]
sub sortingAZ {
{ $fname{$a} cmp $fname{$b} };
}
[/red]

for(sort [red]sortingAZ[/red] keys %people) {
    print_person($_) unless $people{$_}{'pid'};
}

sub print_person {
    my $id = shift;
    $depth++;
    print "<br>", "&nbsp;&nbsp;" x $depth, "<b>", join(' ', @{$people{$id}}{'fname', 'lname'}), "</a></b>" , " ($id)", " \n";
   	for(sort [red]sortingAZ[/red] keys %people) {
        print_person($_) if $people{$_}{'pid'} == $id;
    }
	
    $depth--;
}


__DATA__
65.00|Roger|Brodie|RB|NY| 
53.00|Jake|Namol|JK|NY|65.00
52.00|Matt|Lamon|MM|NY|53.00
51.00|Litia|Lumberg|LM|NY|53.00
54.00|Peter|Givens|BV|NY| 
57.00|Rob|Lumen|RB|NY|54.00
59.00|Lopez|Lucas|LL|NY|54.00
 
This sorts on first and last name. Also, I split the print statement across lines to make it more digestable.
Code:
#!/usr/bin/perl

print "Content-type: text/html\n\n";

while(<DATA>) {
chomp;
my ($id,$fname,$lname,$x,$y,$pid)=split(/\|/);
@{$people{$id}}{'pid', 'fname','lname','x', 'y'} = ($pid+0, $fname, $lname, $x, $y);
}

my $depth = -1;

[red]sub sortingAZ { $people{$a}{'fname'}.$people{$a}{'lname'} cmp $people{$b}{'fname'}.$people{$b}{'lname'} }[/red]

for(sort sortingAZ keys %people) {
    print_person($_) unless $people{$_}{'pid'};
}

sub print_person {
    my $id = shift;
    $depth++;
    [red]print "<br>",
        "&nbsp;&nbsp;" x $depth, "<b>",
        join(' ', @{$people{$id}}{'fname', 'lname'}),
        "</a></b>" , " ($id)", " \n";[/red]

    for(sort sortingAZ keys %people) {
        print_person($_) if $people{$_}{'pid'} == $id;
    }

    $depth--;
}


__DATA__
65.00|Roger|Brodie|RB|NY| 
53.00|Jake|Namol|JK|NY|65.00
52.00|Matt|Lamon|MM|NY|53.00
51.00|Litia|Lumberg|LM|NY|53.00
54.00|Peter|Givens|BV|NY| 
57.00|Rob|Lumen|RB|NY|54.00
59.00|Lopez|Lucas|LL|NY|54.00

Glad to help.

--jim
 
Jim: Thanks again. Your help is really appreciated.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top