File Coverage

blib/lib/Bio/Gonzales/Util.pm
Criterion Covered Total %
statement 36 85 42.3
branch 8 48 16.6
condition 3 12 25.0
subroutine 9 15 60.0
pod 4 10 40.0
total 60 170 35.2


line stmt bran cond sub pod time code
1             #Copyright (c) 2011 Joachim Bargsten <code at bargsten dot org>. All rights reserved.
2              
3             package Bio::Gonzales::Util;
4              
5 31     31   226110 use warnings;
  31         94  
  31         1044  
6 31     31   162 use strict;
  31         64  
  31         577  
7 31     31   142 use Carp;
  31         65  
  31         1688  
8              
9 31     31   15529 use String::ShellQuote;
  31         27524  
  31         1993  
10              
11 31     31   359 use base 'Exporter';
  31         62  
  31         37862  
12             our ( @EXPORT, @EXPORT_OK, %EXPORT_TAGS );
13             our $VERSION = '0.083'; # VERSION
14              
15             @EXPORT = qw();
16             %EXPORT_TAGS = ();
17             @EXPORT_OK
18             = qw(undef_slice slice invslice flatten hash_merge as_arrayref sys_pipe sys_fmt sys_pipe_fatal deep_value);
19              
20             sub slice {
21 1     1 1 123 my ( $hr, @k ) = @_;
22              
23 1         2 my $kk;
24 1 50 33     7 if ( @k == 1 && ref( $k[0] ) eq 'ARRAY' ) {
25 0         0 $kk = $k[0];
26             } else {
27 1         2 $kk = \@k;
28             }
29              
30 1         5 my @valid_keys = grep { exists( $hr->{$_} ) } @$kk;
  3         8  
31              
32 1         5 return undef_slice( $hr, \@valid_keys );
33             }
34              
35             sub invslice {
36 0     0 1 0 my ( $hr, @k ) = @_;
37              
38 0         0 my $kk;
39 0 0 0     0 if ( @k == 1 && ref( $k[0] ) eq 'ARRAY' ) {
40 0         0 $kk = $k[0];
41             } else {
42 0         0 $kk = \@k;
43             }
44              
45 0         0 my %inv = map { $_ => 1 } @$kk;
  0         0  
46              
47 0         0 my %ret;
48 0         0 for my $k ( keys %$hr ) {
49 0 0       0 next if ( exists( $inv{$k} ) );
50 0         0 $ret{$k} = $hr->{$k};
51             }
52              
53 0 0       0 return wantarray ? %ret : \%ret;
54             }
55              
56             sub undef_slice {
57 2     2 1 925 my ( $hr, @k ) = @_;
58              
59 2         3 my $kk;
60 2 100 66     13 if ( @k == 1 && ref( $k[0] ) eq 'ARRAY' ) {
61 1         2 $kk = $k[0];
62             } else {
63 1         3 $kk = \@k;
64             }
65              
66 2         3 my %ret;
67 2         9 @ret{@$kk} = @$hr{@$kk};
68              
69 2 50       9 return wantarray ? %ret : \%ret;
70             }
71              
72             sub flatten {
73 6 100   6 1 14 return map { ref eq 'ARRAY' ? flatten(@$_) : $_ } @_;
  15         50  
74             }
75              
76             sub hash_merge {
77 14     14 0 37 my ( $target, $source ) = @_;
78              
79 14         311 for ( keys %$source ) {
80 1442 50       2705 if ( 'ARRAY' eq ref $target->{$_} ) {
    50          
81 0         0 push @{ $target->{$_} }, @{ $source->{$_} };
  0         0  
  0         0  
82             } elsif ( 'HASH' eq ref $target->{$_} ) {
83 0         0 merge( $source->{$_}, $target->{$_} );
84             } else {
85 1442         3018 $target->{$_} = $source->{$_};
86             }
87             }
88             }
89              
90             sub as_arrayref {
91 0     0 0   my ($item) = @_;
92              
93 0 0         return unless ( defined($item) );
94              
95 0 0         if ( ref $item eq 'ARRAY' ) {
    0          
96 0           return $item;
97             } elsif ( !ref $item ) {
98 0           return [$item];
99             } else {
100 0           return $item;
101             }
102             }
103              
104             sub sys_fmt {
105 0     0 0   my $cmd;
106              
107 0           for my $e (@_) {
108 0 0         if ( ref $e eq 'ARRAY' ) {
    0          
    0          
109 0           $cmd .= shell_quote(@$e) . " ";
110             } elsif ( $e =~ /^>>|\d?>|<|<<|\||\d?>\&\d$/ ) {
111 0           $cmd .= $e . " ";
112             } elsif ( defined $e ) {
113 0           $cmd .= shell_quote($e) . " ";
114             } else {
115 0           next;
116             }
117             }
118 0           chomp $cmd;
119              
120 0           return $cmd;
121             }
122              
123             sub sys_pipe {
124 0     0 0   my $cmd = sys_fmt(@_);
125 0 0         system($cmd) == 0 or croak "system failed: $?\n$cmd";
126             }
127              
128             sub sys_pipe_fatal {
129 0     0 0   my $cmd = 'set -o pipefail; ' . sys_fmt(@_);
130 0 0         system($cmd) == 0 or croak "system " . join( " ", @_ ) . " FAILED: $? ## $!";
131             }
132              
133             sub deep_value {
134 0     0 0   my ( $data, $keys ) = ( shift, shift );
135              
136 0 0 0       $keys = [$keys] if ( defined($keys) && !ref $keys );
137              
138 0           for my $k (@$keys) {
139 0           my $type = ref $data;
140 0 0         if ( !$type ) {
    0          
    0          
    0          
141 0           die "key >$k< cannot be resolved (beyond max level)";
142             } elsif ( $type eq 'ARRAY' ) {
143 0 0         die "key >$k< cannot be resolved (non-existent)" unless ( exists( $data->[$k] ) );
144 0           $data = $data->[$k];
145             } elsif ( $type eq 'HASH' ) {
146 0 0         die "key >$k< cannot be resolved (non-existent)" unless ( exists( $data->{$k} ) );
147 0           $data = $data->{$k};
148             } elsif ( $type eq 'CODE' ) {
149 0           $data = $data->($k);
150             } else {
151 0           croak "type $type not supported";
152             }
153             }
154 0           return $data;
155             }
156             1;
157              
158             __END__
159              
160             =head1 NAME
161              
162             Bio::Gonzales::Util - Utility functions for common tasks
163              
164             =head1 SYNOPSIS
165              
166             use Bio::Gonzales::Util qw(undef_slice slice invslice flatten hash_merge as_arrayref);
167              
168             =head1 SUBROUTINES
169              
170             =over 4
171              
172             =item B<< %sliced_hash = slice(\%hash, @keys_to_slice) >>
173              
174             =item B<< $sliced_hash = slice(\%hash, \@keys_to_slice) >>
175              
176             return a new hash with all keys removed that are not in C<@keys_to_slice>.
177              
178             =item B<< $sliced_hash = undef_slice(\%hash, \@keys_to_slice) >>
179              
180             =item B<< %sliced_hash = undef_slice(\%hash, @keys_to_slice) >>
181              
182             same as slice, but if a key in C<@keys_to_slice> does not exist in C<%hash>,
183             it will result in a additional entry with its value undefined
184            
185             my %hash = (
186             a => 1,
187             b => 2,
188             c => 3
189             );
190              
191             my %sliced_hash = undef_slice(\%hash, qw/a b d/);
192              
193             # will result in
194             %sliced_hash = (
195             a => 1,
196             b => 2,
197             d => undef
198             );
199              
200             =item B<< %sliced_hash = invslice(\%hash, @keys_to_exclude) >>
201              
202             =item B<< \%sliced_hash = invslice(\%hash, \@keys_to_exclude) >>
203              
204             =item B<< @elements = flatten($nested_array1, $nested_array2) >>
205              
206             =back
207              
208             =head1 SEE ALSO
209              
210             =head1 AUTHOR
211              
212             jw bargsten, C<< <joachim.bargsten at wur.nl> >>
213              
214             =cut