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 SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Hash - how to print value if key exists

Status
Not open for further replies.

bigbalbossa

Programmer
Mar 21, 2002
87
0
0
US
Guys/Gals

I've created a hash with List Code being key, and value being the count:
Code:
open(F1, "file1") || die ...
while(<F1>) {
$hash{$LIST}++;
}
Now, i'm bumping this against data in another file and need to print the count if List Code matches:
Code:
open(F2, "file2") || die ...
my $LIST2 = substr($file, 525,5);
	
if(exists($hash{$LIST2}))
{
  $list_cnt = ??? (value of hash)
}

I'm sure it's something simple i'm missing [sadeyes]
 
Your code makes little sense to me. This appears to only count the number of lines in the file:

Code:
open(F1, "file1") || die ...
while(<F1>) {
$hash{$LIST}++;
}

Here you open file2 and never do anything with it:

Code:
open(F2, "file2") || die ...
my $LIST2 = substr($file, 525,5);
    
if(exists($hash{$LIST2}))
{
  $list_cnt = ??? (value of hash)
}

There appears to be no connection between the opening of the file and the subsequent lines. But maybe this is what you are wanting:

Code:
my $LIST2 = substr($file, 525,5);
    
if(exists($hash{$LIST2}))
{
  $list_cnt = $hash{$LIST2};
}

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I apologize for that explanation...when i re-read, it didn't make sense to me. What i'm trying to do is:

1. read a fixed length file
2. create a hash with LIST_CODE as key and an incremented count as the value.
Code:
02346=>34
04532=>1
49445=>397
etc...
3. Now, go back through the fixed length file again. Where LIST_CODE matches the hash, print the value (or total count) for each record. Basically, creating a TOTAL_COUNT field for each record. I need this value for a backend process.

Code:
02346=>34
02346=>34
02346=>34
02346=>34
02346=>34
04532=>1
04532=>1
04532=>1
49445=>397
49445=>397
49445=>397
49445=>397
49445=>397


Make better sense?
 
You can just create a hash as you go with

$hash{$LIST_CODE}{count}++;
$hash{$LIST_CODE}{total} += $value;

What does your example data look like exactly?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
Sample data(first 5 bytes is List Code):

00003 first name1
04352 first name2
99343 first name3
04352 first name4
99343 first name5
99343 first name6
output (w/ new total count field):

00003 first name1 1
04352 first name2 2
99343 first name3 3
04352 first name4 2
99343 first name5 3
99343 first name6 3
 
Okay.. are you worried about the ordering of the output?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
Not so much. Just have to make sure the TOTAL_COUNT matches the list code.
 
There is probably a better way but this works:

Code:
[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url][red]([/red]FILE, [red]"[/red][purple]test.txt[/purple][red]"[/red][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]can't open file: [blue]$![/blue][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[olive][b]while[/b][/olive] [red]([/red]<FILE>[red])[/red][red]{[/red]
	[url=http://perldoc.perl.org/functions/chomp.html][black][b]chomp[/b][/black][/url] [blue]$_[/blue][red];[/red]
	[red]([/red][blue]$list_count[/blue], [blue]$name[/blue][red])[/red] = [url=http://perldoc.perl.org/functions/split.html][black][b]split[/b][/black][/url] [red]/[/red][purple][purple][b]\s[/b][/purple]+[/purple][red]/[/red], [blue]$_[/blue],[fuchsia]2[/fuchsia][red];[/red]
	[blue]$hash[/blue][red]{[/red][blue]$list_count[/blue][red]}[/red]++[red];[/red]
	[blue]$hash2[/blue][red]{[/red][blue]$list_count[/blue][red]}[/red][red]{[/red][blue]$name[/blue][red]}[/red] = [fuchsia]1[/fuchsia][red];[/red]
[red]}[/red]



[olive][b]for[/b][/olive] [blue]$list_count[/blue] [red]([/red][url=http://perldoc.perl.org/functions/sort.html][black][b]sort[/b][/black][/url] [url=http://perldoc.perl.org/functions/keys.html][black][b]keys[/b][/black][/url] [blue]%hash[/blue][red])[/red] [red]{[/red]
	[olive][b]for[/b][/olive] [blue]$name[/blue] [red]([/red][black][b]sort[/b][/black] [black][b]keys[/b][/black] [blue]%[/blue][red]{[/red][blue]$hash2[/blue][red]{[/red][blue]$list_count[/blue][red]}[/red][red]}[/red][red])[/red] [red]{[/red]
		[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple][blue]$list_count[/blue] [blue]$name[/blue] [blue]$hash[/blue]{[blue]$list_count[/blue]}[purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
	[red]}[/red]
[red]}[/red]



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
If you really don't care about the ordering you can get rid of the 2 sort's and it will help performance.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
Thanks travs...works beautifully, except one thing:

I need the total count print on each row, your way is cool, but it's groups them by list code.

so, if list 02222 appears 10 times in the file, the output needs to be:

02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10

Sorry i've been confusing.
 
So do you want
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10
02222 10

or
02222 name1 10
02222 name2 10
02222 name3 10
02222 name4 10

and so on?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
I'll need all the data + total count:

02222 name1 10
02222 name2 10
02222 name3 10
02222 name4 10

But, sometimes list code may not be the first five bytes...could be in the middle.
 
My script turns this
Code:
00003    first name1
04352    first name2
99343    first name3
04352    first name4
99343    first name5
99343    first name6

into this
Code:
00003 first name1 1
04352 first name2 2
04352 first name4 2
99343 first name3 3
99343 first name5 3
99343 first name6 3

What has the counts on the right hand side and retains the list code to name mappings.

I don't mind helping but you can't keep changing the conditions of what you are trying to do. Why don't you provide the real data inputs if you are going to have different conditions.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those Who Say It Cannot Be Done Are Usually Interrupted by Someone Else Doing It; Give the wrong symptoms, get the wrong solutions;
 
Sorry boss...appreciate the help.

This also works, but like you said, i'm sure there a more efficient way to do it:

Code:
use strict;

my $cnt = 0;
my %hash = ();

open(F1, "input1.txt") or die "can't open file: $!\n";
while(<F1>)
{
	chomp $_;
	
	my $list_code = substr($_,525,5);
	$hash{$list_code}{cnt}++;
}

open(F2, "input1.txt") or die "can't open file: $!\n";
while(<F2>)
{
	chomp $_;
	
	my $list_code2 = substr($_,525,5);

  if(exists($hash{$list_code2}))
  {
  	my $tot_cnt = $hash{$list_code2}{cnt};
  	print "$_$tot_cnt\n";
  }
}
 
I'm not bothering to read any of the other posts. However, the above can be simplified because you are looping over the same data, and therefore hash key existence is guaranteed.

Code:
[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]Tie::File[/green][red];[/red]

[black][b]use[/b][/black] [green]strict[/green][red];[/red]

[url=http://perldoc.perl.org/functions/tie.html][black][b]tie[/b][/black][/url] [url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]@array[/blue], [red]'[/red][purple]Tie::File[/purple][red]'[/red], [red]"[/red][purple]input1.txt[/purple][red]"[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Can't open file: [blue]$![/blue][/purple][red]"[/red][red];[/red]

[black][b]my[/b][/black] [blue]%codecount[/blue] = [red]([/red][red])[/red][red];[/red]

[olive][b]for[/b][/olive] [red]([/red][blue]@array[/blue][red])[/red] [red]{[/red]
	[black][b]my[/b][/black] [blue]$code[/blue] = [url=http://perldoc.perl.org/functions/substr.html][black][b]substr[/b][/black][/url] [blue]$_[/blue], [fuchsia]525[/fuchsia], [fuchsia]5[/fuchsia][red];[/red]
	[blue]$codecount[/blue][red]{[/red][blue]$code[/blue][red]}[/red]++[red];[/red]
[red]}[/red]

[olive][b]for[/b][/olive] [red]([/red][blue]@array[/blue][red])[/red] [red]{[/red]
	[black][b]my[/b][/black] [blue]$code[/blue] = [black][b]substr[/b][/black] [blue]$_[/blue], [fuchsia]525[/fuchsia], [fuchsia]5[/fuchsia][red];[/red]
	[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple][blue]$_[/blue][blue]$codecount[/blue]{[blue]$code[/blue]}[purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[red]}[/red]

[url=http://perldoc.perl.org/functions/untie.html][black][b]untie[/b][/black][/url] [blue]@array[/blue][red];[/red]
[tt]------------------------------------------------------------
Pragmas (perl 5.8.8) used :
[ul]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[/ul]
Core (perl 5.8.8) Modules used :
[ul]
[li]Tie::File - Access the lines of a disk file via a Perl array[/li]
[/ul]
[/tt]

- Miller
 
Thanks Miller...i ran a test on both solutions. Opening the file twice seems to be much faster.

Opening Twice:
real 0m2.41s
user 0m1.70s
sys 0m0.71s

Tie::File:
real 1m48.53s
user 1m40.45s
sys 0m7.98s

Thanks for the solution...i learned something new.

 
Yes, Tie::File is mostly useful for in-place editing and manipulation of a text file. It's also useful for more aesthetic parsing.

However, one thing it's not good for is speed. It doesn't surprise me that the former way would be faster.

- Miller
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top