Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Getting rid of a temporary variable in AoH

by j0se (Pilgrim)
on Jun 11, 2013 at 13:56 UTC ( #1038259=perlquestion: print w/ replies, xml ) Need Help??
j0se has asked for the wisdom of the Perl Monks concerning the following question:

Hello, how can I leave out the temporary %users variable?

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my @users; while ( my $line = <> ) { chomp $line; my @fields = qw( login uid gid name home + shell ); $line =~ /^ ([\-\w]+):x:(\d+):(\d+):([\-\w\s\(\)\,]*):([\w\/]+) +:([\w\/]+)$/x or die "Malformed input [$line]"; my %users; @users{@fields} = ($1, $2, $3, $4, $5, $6); push @users, \%users; } print Dumper \@users;

Update: any other code improvements are welcome ... :-)

Well done is better than well said. -- Benjamin Franklin

Comment on Getting rid of a temporary variable in AoH
Select or Download Code
Re: Getting rid of a temporary variable in AoH
by ww (Bishop) on Jun 11, 2013 at 14:04 UTC
    Easiest way (but not idiot proof): simply don't capture it in the first place.

    If you didn't program your executable by toggling in binary, it wasn't really programming!

Re: Getting rid of a temporary variable in AoH
by Corion (Pope) on Jun 11, 2013 at 14:07 UTC
Re: Getting rid of a temporary variable in AoH
by choroba (Canon) on Jun 11, 2013 at 14:08 UTC
    Once the @fields array is declared inside the loop, you can safely destroy it:
    while ( my $line = <DATA> ) { chomp $line; my @fields = qw( login uid gid name home + shell ); my @items = $line =~ /^([\-\w]+):x:(\d+):(\d+):([\-\w\s\(\)\,]*):([\w\/]+) +:([\w\/]+)$/ or die "Malformed input [$line]"; push @users, {}; $users[-1]{ shift @fields } = shift @items while @fields; }
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      A variation (imagine the  my $datum = shift @data is reading a file; no need to create  @fields array each time through loop; state only available with 5.10+; either version works the same):

      >perl -wMstrict -MData::Dump -lE "my @data = ( 'foo 123 %^&', 'huggle 9876 @*', 'ab 55555 !@$%^&', ); ;; my @users; while (my $datum = shift @data) { # use constant FIELDS => qw( alphas digits stuff) +; state $fields = [ qw( alphas digits stuff) ] +; my @items = $datum =~ m{ ([[:alpha:]]+) \s+ (\d+) \s+ ([^[:alpha:]\ +d]+) }xms; # @{ $users[@users] }{ FIELDS() } = @items; @{ $users[@users] }{ @$fields } = @items; } ;; dd \@users; " [ { alphas => "foo", digits => 123, stuff => "%^&" }, { alphas => "huggle", digits => 9876, stuff => "\@*" }, { alphas => "ab", digits => 55555, stuff => "!\@\$%^&" }, ]
Re: Getting rid of a temporary variable in AoH
by hdb (Prior) on Jun 11, 2013 at 14:36 UTC

    For you to judge whether this is an improvement ;)

    use strict; use warnings; use Data::Dumper; use List::MoreUtils qw( mesh ); my @users = map { { mesh @{[ qw( login uid gid name home shell ) ]}, @{[ /^([\-\w]+):x:(\d+):(\d+):([\-\w\s\(\)\,]*):([ +\w\/]+):([\w\/]+)$/ ]} } } <DATA>; print Dumper \@users; __DATA__ hdb:x:1111:2222:hdb:/home/hdb:/bin/bash

    UPDATE: Above is too complicated, look at this:

    use strict; use warnings; use Data::Dumper; my @users = map { /^([\-\w]+):x:(\d+):(\d+):([\-\w\s\(\)\,]*):([\w\/]+):([\w\/]+)$/; { login => $1, uid => $2, gid => $3, name => $4, home => $5, shell = +> $6 } } <DATA>; print Dumper \@users; __DATA__ hdb:x:1111:2222:hdb:/home/hdb:/bin/bash
Re: Getting rid of a temporary variable in AoH
by hbm (Hermit) on Jun 11, 2013 at 14:56 UTC

    Interesting, I was also thinking of yesterday's "splice/mesh" discussion. (I wouldn't really do it this way.)

    But do notice in your RE, I changed delimiter and did not escape forward slashes, commas or hyphens.

    use strict; use warnings; use List::MoreUtils qw(mesh); use Data::Dumper; my @users; my @fields = qw(login uid gid name home shell); while (<DATA>) { m#^\s*([\w-]+):x:(\d+):(\d+):([\w\s\(\),-]*):([\w/]+):([\w/]*)$# or die "Malformed input [$_]"; push @users, { mesh @fields, @{[//]} }; } print Dumper \@users; __DATA__ root:x:0:0::/:/usr/bin/ksh paul:x:201:1::/home/paul:/usr/bin/ksh jdoe:x:202:1:John Doe:/home/jdoe:/usr/bin/ksh

    Update: The parens don't need to be escaped either:

    m#^\s*([\w-]+):x:(\d+):(\d+):([\w\s(),-]*):([\w/]+):([\w/]*)$#

      If the format of the input is as fixed as in case of a passwd file, then splitting on colon makes much more sense, even if one needs to chomp in that case.



      Or using named captures:
      use strict; use warnings; use Data::Dumper; my @users; while (<DATA>) { m#^\s*(?<login>[\w-]+) :x :(?<uid>\d+) :(?<gid>\d+) :(?<name>[\w\s(),-]*) :(?<home>[\w/]+) :(?<shell>[\w/]*)$#x or die "Malformed input [$_]"; push @users, { %+ }; } print Dumper \@users; __DATA__ root:x:0:0::/:/usr/bin/ksh paul:x:201:1::/home/paul:/usr/bin/ksh jdoe:x:202:1:John Doe:/home/jdoe:/usr/bin/ksh

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1038259]
Approved by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (8)
As of 2015-07-03 17:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (54 votes), past polls