programminglearner
programminglearner

Reputation: 542

File containing columns from different files Perl

I want to combine multiple columns from 2 files.

First File ex:

Name   Age
Bob    22
Carl   19
Daniel 29
Frank  31
Zach   22

Second File ex: (THERE IS NO GPA VALUE FOR DANIEL SO WE LEAVE IT EMPTY)

Name   GPA
Bob    3.0
Carl   3.5
Daniel
Frank  2.6
Zach   2.9

I want to ouput something that looks like

Name   Age    GPA
Bob    22     3.0
Carl   19     3.5
Daniel 29
Frank  31     2.6
Zach   22     2.9

Since the names are the same, I can use the first column of either file.

Here is the code I have so far, but it's not outputting anything.

unless (open COL1, '<'. $file1) {die "Couldn't open '$file1'\n";}
unless (open COL2, '<'. $file2) {die "Couldn't open '$file2'\n";}

my %feature;
my @files = (scalar <COL1>, scalar <COL2>);

for my $file (@files) {
    open my $infh, '<', $file or die $!;
    while (<$infh>) {
        chomp;
        my ($feature, $value) = split /\s+/, $_;
        push @{$feature{$feature}}, $value;
    }
}
close COL1;
close COL2;
foreach my $k (keys %feature) {
    print "$k @{$feature{$k}}\n";
}

How can I fix this so that it takes the first and second column from the first file and appends the second column from the second file onto it? (I want it in the order of Name, Age, GPA).

Upvotes: 0

Views: 44

Answers (2)

Shawn
Shawn

Reputation: 52364

Much as I like perl... non-perl shell one-liner:

$ join --header -t $'\t' file1.txt file2.txt
Name    Age     GPA
Bob     22      3.0
Carl    19      3.5
Daniel  29
Frank   31      2.6
Zach    22      2.9

(Does require bash, zsh, or another shell that understands $'\t' literals, as well as GNU join. Also assumes the files are sorted like your example.)

Upvotes: 1

ikegami
ikegami

Reputation: 385789

use List::Util qw( max );

my %students;

{
    open(my $fh, '<', $qfn1)
       or die("Can't open \"$qfn1\": $!\n");
    while (<$fh>) {
        my ($name, $age) = split;
        $students{$name}{age} = $age;
    }
}

{
    open(my $fh, '<', $qfn2)
       or die("Can't open \"$qfn2\": $!\n");
    while (<$fh>) {
        my ($name, $gpa) = split;
        $students{$name}{gpa} = $gpa;
    }
}

my $max_name_len = max map length, "Name", keys %students;
my $max_age_len  = max map length, "Age", grep defined, map $_->{age}, values %students;
my $max_gpa_len  = max map length, "GPA", grep defined, map $_->{gpa}, values %students;

printf("%-*s %-*s %-*s\n",
    $max_name_len, "Name",
    $max_age_len,  "Age",
    $max_gpa_len,  "GPA",
);

for my $name (sort keys %students) {
    my $student = $students{$name};
    my $age = $student->{age};
    my $gpa = $student->{gpa};
    printf("%-*s %*s %*s\n",
        $max_name_len, $name,
        $max_age_len,  $age // "",
        $max_gpa_len,  $gpa // "",
    );
}

Upvotes: 2

Related Questions