Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
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 (Abbot) 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 meditating upon the Monastery: (12)
As of 2014-09-16 21:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (49 votes), past polls