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!

sorting by user and counting

Status
Not open for further replies.

vquick

IS-IT--Management
Jul 13, 2008
14
0
0
US
sorry this my first post im trying to sort a list by user name and count the different functions they have done with time they did each function. here is example of what a file looks like:

user;work;workgroup;function;start time;comp time
user1;ef1;1;1;10/12/09 8:00;10/12/09 10:00
user1;ef2;1;1;10/12/09 11:00;10/12/09 12:00
user1;ef3;1;2;10/12/09 13:00:00;10/12/09 15:00
user2;efs1;1;1;10/12/09 8:00;10/12/09 10:00
user2;efs2;1;2;10/12/09 10:00;10/12/09 15:00
user2;efs3;1;2;10/12/09 16:00;10/12/09 18:00

I would expect my output to look like this:
user function count

user1 1 2 3hrs0min
user1 2 1 2hrs0min
user2 1 1 2hrs0min
user2 2 2 9hrs0min

I hope this make sense. here is what i have tried:
<IN> would be the example file above


for (<IN>) {
chomp;
my ($user,$work,$wg,$func,$start_time, $comp_time) = split(";", $_);

if (!$seen{$user}{$work}) {
$seen{$user}{$work}++;
if ($func == 1){
$funcone++;
push(@one, $
}
if ($func == 2){
$functwo++;
}
if ($func == 3){
$functhree++;

}

}

if ($funcone ne ""){
print "$user $func $funcone\n";
}
if ($functwo ne ""){
print "$user$func $functwo\n";
}
if ($functhree ne ""){
print "$user $func $functhree\n";
}



}

ive also tried data dumper. it works but i cant get it print out like i want. here is the data dumper code:

#!/usr/bin/perl

use strict;
use warnings;

use Data::Dumper;

# Make Data::Dumper pretty
$Data::Dumper::Sortkeys = 1;
$Data::Dumper::Indent = 1;

# Set maximum depth for Data::Dumper, zero means unlimited
$Data::Dumper::Maxdepth = 0;

my %seen = ();
my %func_counts = ();

while( <DATA> ){
chomp;
my ($user,$work,$wg,$func,$start_time,$comp_time) = split(";", $_);
unless( $seen{$user}{$work} ){
$seen{$user}{$work} ++;
$func_counts{$user}{$func} ++;
}
}
print Dumper \%seen, \%func_counts;

__DATA__
user1;ef1;1;1;10/12/09 8:00;10/12/09 10:00
user1;ef2;1;1;10/12/09 11:00;10/12/09 12:00
user1;ef3;1;2;10/12/09 13:00:00;10/12/09 15:00
user2;efs1;1;1;10/12/09 8:00;10/12/09 10:00
user2;efs2;1;2;10/12/09 10:00;10/12/09 15:00
user2;efs3;1;2;10/12/09 16:00;10/12/09 18:00
 
How about something like:

Code:
use Time::Local;

my %users;
while (<DATA>) {
	chomp;
	my ($user, $work, $group, $function, $start, $end) = split /;/, $_;
	my ($month, $day, $year, $hour, $minute, $second);
	
	if ($start =~ m!(\d+)/(\d+)/(\d+)\s*(\d+):(\d+):(\d+)!) {
		($month, $day, $year, $hour, $minute, $second) = ($1, $2, $3, $4, $5, $6);
	} elsif ($start =~ m!(\d+)/(\d+)/(\d+)\s*(\d+):(\d+)!) {
		($month, $day, $year, $hour, $minute, $second) = ($1, $2, $3, $4, $5, 0);
	} else {
		die "$start - unrecognized time format";
	}
	$start = timegm(0, $minute, $hour, $day, $month-1, $year);

	
	if ($end =~ m!(\d+)/(\d+)/(\d+)\s*(\d+):(\d+):(\d+)!) {
		($month, $day, $year, $hour, $minute, $second) = ($1, $2, $3, $4, $5, $6);
	} elsif ($end =~ m!(\d+)/(\d+)/(\d+)\s*(\d+):(\d+)!) {
		($month, $day, $year, $hour, $minute, $second) = ($1, $2, $3, $4, $5, 0);
	} else {
		die "$end - unrecognized time format";
	}
	$end = timegm(0, $minute, $hour, $day, $month-1, $year);
	
	$users{$user}{$function}{count}++;
	$users{$user}{$function}{time} += $end - $start;
	
	
}

foreach my $name (sort keys %users) {
	foreach my $function (sort keys %{$users{$name}}) {
		print join(" ", $name, $function, $users{$name}{$function}{count},
					calc_hours_mins($users{$name}{$function}{time})), "\n";
	}
}

sub calc_hours_mins {
	my $hours = int($_[0] / 3600);
	my $mins = ($_[0] % 3600) / 60;
	return "${hours}hours${mins}mins";
}

__DATA__
user1;ef1;1;1;10/12/09 8:00;10/12/09 10:00
user1;ef2;1;1;10/12/09 11:00;10/12/09 12:15
user1;ef3;1;2;10/12/09 13:00:00;10/12/09 15:00
user2;efs1;1;1;10/12/09 8:00;10/12/09 10:07
user2;efs2;1;2;10/12/09 10:00;10/12/09 15:00
user2;efs3;1;2;10/12/09 16:00;10/12/09 18:12
 
Can't really see the relationship between your code and your goal.
This is my solution with a simplified (and less general) treatment of durations:
Code:
while(<DATA>){ 
  chomp; 
  my($user,$work,$wg,$func,$start_time,$comp_time)=split/;/; 
  $seen{$user}{$func}[0]++;
  $seen{$user}{$func}[1]+=timedif($start_time,$comp_time);
}
for my$u(sort keys%seen){
  for(sort keys%{$seen{$u}}){
    my$d=$seen{$u}{$_}[1];
    $d=int($d/60).'hrs'.($d%60).'min';
    print"$u $_ $seen{$u}{$_}[0] $d\n";
  }
}
sub timedif{
    #no error checking performed; maximum time difference= 24 hrs
  my($st,$en)=@_;
  my($ds,$hs)=split/ /,$st;
  my($hss,$mss)=split/:/,$hs;
  $st=$hss*60+$mss;
  my($de,$he)=split/ /,$en;
  my($hee,$mee)=split/:/,$he;
  $en=$hee*60+$mee;
  if($ds eq $de){
    $en-=$st;
  }else{
    $en-=$st-1440;
  }
  return$en;
}
__DATA__
user1;ef1;1;1;10/12/09 8:00;10/12/09 10:00
user1;ef2;1;1;10/12/09 11:00;10/12/09 12:00
user1;ef3;1;2;10/12/09 13:00:00;10/12/09 15:00
user2;efs1;1;1;10/12/09 8:00;10/12/09 10:00
user2;efs2;1;2;10/12/09 10:00;10/12/09 15:00
user2;efs3;1;2;10/12/09 16:00;10/12/09 18:00

Franco
: Online engineering calculations
: Magnetic brakes for fun rides
: Air bearing pads
 
Very similar solution to rharsh's (I copied parts of his calc_hours_mins function). Very general/compact, doesn't make any use of the date (only time). If the duration extends over 2 dates then you should make use of a module such as Date::Calc (Date_to_Days function).

Code:
my %output;

while (<IN>) {
	my ($user, $work, $workgroup, $function, $starttime, $comptime) = split(/\;/,$_);
	my ($sday, $smonth, $syear, $shour, $sminute) = split(/\/|\s|:/,$starttime);
	my ($cday, $cmonth, $cyear, $chour, $cminute) = split(/\/|\s|:/,$comptime);
	
	$output{$user}{$function}{'Count'}++;
	$output{$user}{$function}{'Time'} += (((($shour*60+$sminute)*60)*-1)-((($chour*60+$cminute)*60)*-1));
}

foreach my $user (sort keys %output) {
	foreach my $function (sort keys %{$output{$user}}) {
		print "$user $function $output{$user}{$function}{'Count'} ".(int($output{$user}{$function}{'Time'}/3600))."hrs".(($output{$user}{$function}{'Time'}%3600)/60)."mins\n";
	}
}

Chris
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top