Re: some suggestions
Thank you everyone. I'm still digesting this, but I do have a better understanding. Chris -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
some suggestions
I would like to use the number on the left as a key in a hash and use the number on the right as the value pair to the key. Then print the values for each hour that have the same key. Maybe this is a good example for an array of hashes, but I not real sure how to begin. Any help is greatly appreciated. Below is the input data: Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 Desired output below: 12 13 14 00012 2 2 00023 3 3 00031 1 1 -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: some suggestions
On 3/22/12 Thu Mar 22, 2012 2:23 PM, Chris Stinemetz chrisstinem...@gmail.com scribbled: I would like to use the number on the left as a key in a hash and use the number on the right as the value pair to the key. Then print the values for each hour that have the same key. Maybe this is a good example for an array of hashes, but I not real sure how to begin. Any help is greatly appreciated. Below is the input data: Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 Desired output below: 12 13 14 00012 2 2 00023 3 3 00031 1 1 I would suggest using a hash-of-hashes. You have a two-level key: the first (primary) key is the hour value: 12, 13, 14. The second (-ary) key is the number from the left-hand column. The value is the number from the right-hand column. So read the file, save the hour keys in a variable (e.g. $hour), extract the two numbers (e.g. $left, $right), and store the values in a two-level hash: $hash{$hour}{$left} = $right; Then, when you have read the entire file, print the data in your desired format. The printing will be a little tricky as you are inverting your data with respect to the keys, so you can't do a simple two-level traversal over the nested hashes and print as you go. If all you want is to print as shown, then you can invert the importance of the keys and use this instead: $inverted_hash{$left}{$hour} = $right; Then you can traverse the left numbers and print the hour values for each one. Sometimes the trick for effective programming is defining the right data structure. -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: some suggestions
On 12-03-22 05:23 PM, Chris Stinemetz wrote: but I not real sure how to begin. Any help is greatly appreciated. Below is the input data: Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 Desired output below: 12 13 14 00012 2 2 00023 3 3 00031 1 1 The first question you should ask yourself when you need to write a script that manipulates data is: Is preserving the input order of the data important? If so, the using an array is the easiest way to do this. In this case, however, the objective is to rearrange the data, so we are free to use any data structure to hold the data. The second question is: What is the best data structure for this task? The possibilities fall into three categories: one similar to the input structure, one similar to the output, and some intermediate one. The advance of the first is that it will take little processing of the input to achieve it but more processing of the output. The second choice is the same as the first but with input and output switched around. The third is the most complex and should only be used as a last resort. But of the first two, which is better? Well, take a look at the structures of the data. The input is linear; it has one datum after another. The output is a table, two dimensional. If we store the data in a linear structure, like its input, we would still have to transform it to a two-dimensional one before we can output it. But if we can transform the input into a two-dimension structure, it can be easily outputted and we save ourselves a step. So, since preserving input order is not important, a hash of hashes seems the best structure. When printing out a table, it's nice to have the column index or key as the inner one and the row index or key as the outer one. The column key is the Hr value, and the row key is from the lines with two numbers. So, the pseudo-code looks like this: Create a variable to hold the Hr key; For each line of input: If the line starts with Hr: Save the number in the Hr variable; Else Extract the key and value from the line; Store it in a HoH with this key, the Hr key and the value $HoH{$key}{$Hr_key} = $value; Now output the table (exercise left to the reader) :). -- Just my 0.0002 million dollars worth, Shawn Programming is as much about organization and communication as it is about coding. [edited for today's programmers] Show me your code and conceal your interfaces, and I shall continue to be mystified. Show me your interfaces, and I won't usually need your code; it'll be obvious. -- Fred Brooks -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: some suggestions
Chris Stinemetz wrote: I would like to use the number on the left as a key in a hash and use the number on the right as the value pair to the key. Then print the values for each hour that have the same key. Maybe this is a good example for an array of hashes, but I not real sure how to begin. Any help is greatly appreciated. Below is the input data: Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 Desired output below: 12 13 14 00012 2 2 00023 3 3 00031 1 1 $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( sort { $a = $b } keys %{ $data{ $row } } ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 00012 2 2 00023 3 3 00031 1 1 John -- Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction. -- Albert Einstein -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: some suggestions
John W. Krahn wrote: $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( sort { $a = $b } keys %{ $data{ $row } } ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 0001 2 2 2 0002 3 3 3 0003 1 1 1 Probably better: $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( @hours ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 00012 2 2 00023 3 3 00031 1 1 John -- Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction. -- Albert Einstein -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: some suggestions
On Fri, Mar 23, 2012 at 10:20 AM, John W. Krahn jwkr...@shaw.ca wrote: John W. Krahn wrote: $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( sort { $a = $b } keys %{ $data{ $row } } ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 0001 2 2 2 0002 3 3 3 0003 1 1 1 Probably better: $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( @hours ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 0001 2 2 2 0002 3 3 3 0003 1 1 1 Here I use: push @hours, $1 if(/Hr\b(.*)\b/) ; $data{$1}{$hours[-1]} = $2 if(/\b(.+)\b(.*)\b/); it reported, how can I fix it: $ perl calen.pl 12 13 14 Argument 0003 1 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument 0002 3 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument 0001 2 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument Hr 12 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument Hr 13 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument Hr 14 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Hr 12 Hr 13 Hr 14 0001 2 0002 3 0003 1l Thanks, -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/
Re: some suggestions
At 10:41 AM +0800 3/23/12, lina wrote: On Fri, Mar 23, 2012 at 10:20 AM, John W. Krahn jwkr...@shaw.ca wrote: John W. Krahn wrote: $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( sort { $a = $b } keys %{ $data{ $row } } ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 0001 2 2 2 0002 3 3 3 0003 1 1 1 Probably better: $ echo Hr 12 0001 2 0002 3 0003 1 Hr 13 0001 2 0002 3 0003 1 Hr 14 0001 2 0002 3 0003 1 | perl -e' my ( @hours, %data ); while ( ) { push @hours, $1 if /^hr\s*(\d+)/i; $data{ $1 }{ $hours[ -1 ] } = $2 if /^(\d+)\s+(\d+)/; } print join( \t, , @hours ), \n; for my $row ( sort { $a = $b } keys %data ) { print $row; for my $col ( @hours ) { print \t$data{$row}{$col}; } print \n; } ' 12 13 14 00012 2 2 00023 3 3 00031 1 1 Here I use: push @hours, $1 if(/Hr\b(.*)\b/) ; $data{$1}{$hours[-1]} = $2 if(/\b(.+)\b(.*)\b/); it reported, how can I fix it: By using the correct regex. You need to use \d or [0-9] in your regular expression rather than the dot character, which matches any character. You are matching and capturing the entire line with (.+), leaving nothing for the second capture group. $ perl calen.pl 12 13 14 Argument 0003 1 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument 0002 3 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument 0001 2 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument Hr 12 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument Hr 13 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Argument Hr 14 isn't numeric in sort at calen.pl line 23, $_[...] line 12. Hr 12 Hr 13 Hr 14 0001 2 0002 3 0003 1l Thanks, -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/ -- Jim Gibson j...@gibson.org -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/