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

Hello guys, I have two files: File A
02,29031990,feb,21,5 02,29031990,feb,18,5 02,29031990,feb,20,5 02,29031990,feb,21,5
File B
Unit4872,29031990,01,0 Unit4873,29031990,03,0 Unit4874,29031990,02,4 Unit4875,29031990,02,3 Unit4876,29031990,02,2 Unit4877,29031990,02,1 Unit4878,29031990,02,0
My keys I have matched are 1st with 2nd column from File A and 2nd with 3rd from file B. My rule is when both keys matched I will print 1st column from File B with 2nd, 1st, 3rd, 4th and 5th from File A and one counter of all rows of the File A. So, with combined these two files I have created this file:
Unit4874,29031990,02,feb,21,5,1 Unit4875,29031990,02,feb,18,5,2 Unit4876,29031990,02,feb,20,5,3 Unit4877,29031990,02,feb,21,5,4
Now my situation is this. If my last number of my counter(in this case is 4) minus the 5th column from File A is 1, I have to get next line from File B adding add 1 more to counter and getting the last result of 4th column from File B. My result would be like that.
Unit4874,29031990,02,feb,21,5,1 Unit4875,29031990,02,feb,18,5,2 Unit4876,29031990,02,feb,20,5,3 Unit4877,29031990,02,feb,21,5,4 Unit4878,29031990,02,feb,21,5,5.
This is my code so far. I was testing but I am caught in this code.
#!/usr/bin/perl use strict; use warnings; use Data::Dumper qw(Dumper); my $filea = $ARGV[0]; my $fileb = $ARGV[1]; open ( FA, '<', $filea) || die ( "File $filea Not Found!" ); open ( FB, '<', $fileb) || die ( "File $fileb Not Found!" ); my %ts; my @LAST_PLC; while ( <FB> ) { chomp; my($Unit, $date, $mnt, $qtde) = split ","; push @{ $ts{$date,$mnt} }, $Unit; push @LAST_PLC, ($Unit); } my $last_one = pop @LAST_PLC; #print $last_one."\n"; my $count=1; my @FIRST_PRICE; my $result; my @FINAL; my $price; while ( <FA> ) { chomp; my($mnt,$date,$att,$idx,$max) = split ","; push @FIRST_PRICE, ($idx); $price = shift @FIRST_PRICE; #if ( exists( $ts{$date,$mnt} ) ){ my $Unit = shift @{$ts{$date,$mnt}}; if ( ( $max - $count ) eq 1 ) { #print join(",", $last_one, $date, $mnt, $att, + $idx, $max, $count)."\n"; #} else { print join(",", $Unit, $date, $mnt, $att, $idx +, $max, $count)."\n"; } #push @FINAL, (join(",", $Unit, $date, $mnt, $att, $id +x, $max, $count, $last_one)."\n"); $count++; #} } #print @FINAL;

Replies are listed 'Best First'.
Re: Controlling the count in array
by jimpudar (Pilgrim) on Jun 08, 2018 at 03:16 UTC

    Hi EBK,

    I am not 100% sure I understood your requirements, but try this out:

    #! /usr/bin/env perl use strict; use warnings; use autodie; use 5.10.0; open my $fa, '<', 'file-a'; open my $fb, '<', 'file-b'; my %fa; my %fb; while (<$fb>) { chomp; my @F = split ','; push @{ $fb{"$F[2]:$F[1]"} }, $_; } while (<$fa>) { chomp; my @F = split ','; push @{ $fa{"$F[0]:$F[1]"} }, $_; } foreach my $key (keys %fa) { for my $i ( 0 .. $#{ $fa{$key} } ) { my @A = split ',', $fa{$key}[$i]; my @B = split ',', $fb{$key}[$i]; say join ',', $B[0], $B[1], $B[2], $A[2], $A[3], $A[4], $i + 1; } if ( @{ $fa{$key} } + 1 == @{ $fb{$key} } ) { my @A = split ',', $fa{$key}[-1]; my @B = split ',', $fb{$key}[-1]; say join ',', $B[0], $B[1], $B[2], $A[2], $A[3], $A[4], scalar @{ $fb{$key} }; } }

    Output:

    Unit4874,29031990,02,feb,21,5,1 Unit4875,29031990,02,feb,18,5,2 Unit4876,29031990,02,feb,20,5,3 Unit4877,29031990,02,feb,21,5,4 Unit4878,29031990,02,feb,21,5,5

    Hope this helps,

    Jim

    Edit: As another monk pointed out in another of your questions, it seems like you could really benefit from some kind of SQL database. Seems like you want to do a join on two tables.

    πάντων χρημάτων μέτρον έστιν άνθρωπος.

      As another monk pointed out in another of your questions, it seems like you could really benefit from some kind of SQL database. Seems like you want to do a join on two tables.

      Actually, I think that using a database would not be the best approach to solve this problem. The problem is where the OP says:

      ...If my last number of my counter(in this case is 4) minus the 5th column from File A is 1... and I have to get next line...

      In terms of relational databases it would mean one has to keep track of rows that have already been processed or 'next' rows or 'last occurrence' rows. Of course it can be done, but as far as I know it is going to be an ugly mess using row counters that each database technology handles differently.

      Besides that using relational database technologies the rule that the OP states: Table A.Column 5 - COUNTER == 1 does not give one row as result but five (marked with *):

      1,02 29031990 feb 21 5, 4,Unit4877 29031990 02 1 2,02 29031990 feb 18 5, 3,Unit4876 29031990 02 2 3,02 29031990 feb 20 5, 2,Unit4875 29031990 02 3 4,02 29031990 feb 21 5, 1,Unit4874 29031990 02 4 4,02 29031990 feb 21 5, 1,Unit4874 29031990 02 4 * 4,02 29031990 feb 21 5, 2,Unit4875 29031990 02 3 * 4,02 29031990 feb 21 5, 3,Unit4876 29031990 02 2 * 4,02 29031990 feb 21 5, 4,Unit4877 29031990 02 1 * 4,02 29031990 feb 21 5, 5,Unit4878 29031990 02 0 *

      The only way to solve that would be something like WHERE (TABLE A.COL5 - COUNTER_A = 1) AND (TABLE A.COL5 = COUNTER_B). Again that means using row counters and on top of that now I am making assumptions about the data and I actually don't want to go there.

      I have seen a couple of examples that EBK has posted and the only thing that I see is that he is being provided with very low quality data. I understand that he is trying to handle it the best way he can but I think that the solution should be coming from the organisation who are providing him this data.

      Here is some code:

      Hi Jim, It's worked however some cases I got "Use of uninitialized value in join or string at" or "Use of uninitialized value in split at". in both files I have coincident matching keys and I can not have records like these:
      ,,,feb,21,5,5
      How can I solve this, a simple defined exists would solve this?

        You could add a check in each of the while loops at the start to validate the data is in the format you expect.

        If you include the portion of the inputs on which the program is failing, I might be able to help you more.

        Best,

        Jim

        πάντων χρημάτων μέτρον έστιν άνθρωπος.

Re: Controlling the count in array
by Veltro (Hermit) on Jun 07, 2018 at 21:25 UTC
    ...If my last number of my counter(in this case is 4) minus the 5th column from File A is 1...

    4-5 is not 1. Maybe you can try -1?

      Sorry but is ($max - $counter) eq 1