File Coverage

blib/lib/Statistics/UIDList.pm
Criterion Covered Total %
statement 84 85 98.8
branch 28 32 87.5
condition 6 6 100.0
subroutine 12 13 92.3
pod 6 6 100.0
total 136 142 95.7


line stmt bran cond sub pod time code
1             package Statistics::UIDList;
2 6     6   181435 use strict;
  6         14  
  6         218  
3 6     6   31 use warnings;
  6         14  
  6         180  
4 6     6   29 use Carp qw/croak/;
  6         15  
  6         12578  
5              
6             our $VERSION = '0.03';
7              
8             sub new {
9 12     12 1 6082 my $class = shift;
10              
11 12         25 my $param = +{};
12              
13 12         34 for my $arg (@_) {
14 25 100       70 if (ref $arg eq 'ARRAY') {
    100          
15 23         27 push @{$param->{lists}}, $arg;
  23         72  
16             }
17             elsif (ref $arg eq 'HASH') {
18 1         3 for my $option (qw/digit/) {
19 1 50       8 $param->{$option} = $arg->{$option} ? $arg->{$option} : undef;
20             }
21             }
22             else {
23 1         187 croak "invalid arg: $arg, @_";
24             }
25             }
26              
27 11         42 bless $param, $class;
28             }
29              
30             sub list {
31 11     11 1 1294 my ($self, $num) = @_;
32              
33 11 100       27 if (defined $num) {
34 3         16 return $self->{lists}->[$num];
35             }
36             else {
37 8 100       35 unless ($self->{_all_list}) {
38 6         10 $self->{_all_list} = [ map { @$_ } @{$self->{lists}} ];
  15         75  
  6         21  
39             }
40 8         39 return $self->{_all_list};
41             }
42             }
43              
44             sub uniq {
45 2     2 1 6 my ($self, $num) = @_;
46              
47 2 100       6 if (defined $num) {
48 1 50       8 return $self->{uniq}->[$num] if $self->{uniq}->[$num];
49 1         4 $self->{uniq}->[$num] = $self->_uniq($self->list($num));
50 1         10 return $self->{uniq}->[$num];
51             }
52              
53 1 50       4 unless ($self->{_all_uniq}) {
54 1         3 $self->{_all_uniq} = $self->_uniq($self->list);
55             }
56 1         7 return $self->{_all_uniq};
57             }
58              
59             sub _uniq {
60 2     2   4 my ($self, $list) = @_;
61              
62 2         2 my %h;
63             my @r;
64 2         2 for my $id (@{$list}) {
  2         4  
65 23 100       66 push @r, $id unless $h{$id};
66 23         33 $h{$id} = 1;
67             }
68              
69 2         9 return \@r;
70             }
71              
72             sub dup {
73 2     2 1 11 my ($self) = @_;
74              
75 2 50       13 return $self->{dup} if $self->{dup};
76              
77 2         6 $self->{dup} = $self->_dup($self->list);
78              
79 2         18 return $self->{dup};
80             }
81              
82             sub _dup {
83 2     2   5 my ($self) = @_;
84              
85 2         4 my %h;
86 2         3 for my $list (@{$self->{lists}}) {
  2         6  
87 5         229 my %e;
88 5         7 for my $id (@{$list}) {
  5         12  
89 34 100       95 $h{$id}++ unless $e{$id};
90 34         70 $e{$id} = 1;
91             }
92             }
93              
94 2         3 my %d;
95             my @dup;
96 2         4 for my $id (@{$self->list}) {
  2         6  
97 34 100 100     191 if (!$d{$id} && $h{$id} == $#{$self->{lists}} + 1) {
  20         163  
98 8         14 push @dup, $id;
99 8         20 $d{$id} = 1;
100             }
101             }
102              
103 2         15 return \@dup;
104             }
105              
106 0     0 1 0 sub duplicate { dup(@_) }
107              
108             sub limit {
109 3     3 1 19 my ($self, $cond) = @_;
110              
111 3         4 my $code;
112 3 100 100     24 if ($cond && $cond =~ m!^\d$!) {
    100          
113 1     12   6 $code = sub { $_[0] >= $cond };
  12         30  
114             }
115             elsif (ref $cond eq 'CODE') {
116 1         3 $code = $cond;
117             }
118             else {
119 1         175 croak "require limit condition";
120             }
121              
122 2         7 return $self->_limit($self->list, $code);
123             }
124              
125             sub _limit {
126 2     2   3 my ($self, $list, $code) = @_;
127              
128 2         3 my %h;
129 2         3 for my $id (@{$list}) {
  2         4  
130 36         57 $h{$id}++;
131             }
132              
133 2         3 my @r;
134 2         4 for my $id (@{$list}) {
  2         3  
135 36 100       119 next unless $h{$id};
136 27 100       70 if ( $code->($h{$id}, $id) ) {
137 6         32 push @r, $id;
138 6         12 $h{$id} = undef; # never pick up
139             }
140             }
141              
142 2         26 return \@r;
143             }
144              
145             1;
146              
147             __END__