Limo has asked for the wisdom of the Perl Monks concerning the following question:

Here's the code:
open (PRV, $private) or die "$!"; while (<PRV>) { chomp; $_ =~ tr/A-Z/a-z/; my @array = split(' ', $_); my $far = @array[0]; my $dev = @array[3]; print "$dev is connected to $far\"; }
This produces, for example:
atlanta is connected to 123 atlanta is connected to 456 atlanta is connected to 789 boston is connected to 12 boston is connected to 34 etc.........
What I want to do is, rather than print "atlanta is connected to "N"" 3 times, I want to simply have it print:
atlanta is connected to: 123, 456, 789 boston is connected to: 12, 34
Can any one help me out?

Replies are listed 'Best First'.
Re (tilly) 1: A Not so Simple Append
by tilly (Archbishop) on Oct 03, 2000 at 01:14 UTC
    First of all your die is not very informative. That should be fixed.

    Secondly what you need to do is walk through the file building up a data structure with your info, then walk through that and print. Something like this (untested) code:

    open (PRV, "<$private") or die "Cannot read $private: $!"; my %connected; while (<PRV>) { chomp; my ($far, $dev) = (split(' ', lc($_)))[0,3]; push @{$connected{$far}}, $dev; } foreach my $dev (sort keys %connected) { my $fars = join ", ", @{$connected{$dev}}; print "$dev is connected to: $fars\n"; }
      Thanks much! It's actually doing the opposite of what I need, but if I stare at it long enough, I can learn what the code is doing! BTW, I do have a more informative "die" statement, but I omitted it to make my post less wordy. Silly me.
Re: A Not so Simple Append
by clemburg (Curate) on Oct 03, 2000 at 01:30 UTC

    You mean like this?

    #!/usr/bin/perl -w use strict; my %seen = (); while (<DATA>) { my ($one, $two) = split; $seen{$one} = [$two, exists $seen{$one} ? @{$seen{$one}} : () ]; } for my $key (keys %seen) { print $key, " ", join(", ", @{$seen{$key}}), "\n"; } __DATA__ a 1 a 2 a 3 a 4 b 1 c 1 d 1

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com

      while (<DATA>) { my ($one, $two) = split; $seen{$one} = [$two, exists $seen{$one} ? @{$seen{$one}} : () +]; }
      You should rely on autovivification rather than recreating the array each time. For example, the easy form of what you wrote is:
      while (<DATA>) { my ($one, $two) = split; push @{$seen{$one}}, $two; }
      If you insist on having the new elements at the beginning, change push to unshift, slightly less efficient.

      -- Randal L. Schwartz, Perl hacker

        Conceptually push and unshift are exactly symmetrical, along with pop and shift. Is there really a performance difference?

        I tried it and wow:

        use strict; use Benchmark; use vars qw(%test); %test = ( push => sub { my @tmp; push @tmp, "bar" foreach 1..10000; }, unshift => sub { my @tmp; unshift @tmp, "bar" foreach 1..10000; }, ); timethese (-5, \%test); __END__ Benchmark: running push, unshift, each for at least 5 CPU seconds... push: 5 wallclock secs ( 5.46 usr + 0.05 sys = 5.51 CPU) @ 17 +.42/s (n=96) unshift: 8 wallclock secs ( 8.08 usr + 0.11 sys = 8.19 CPU) @ 0 +.73/s (n=6)
        Why is the one so much faster than the other?

        Thanks for pointing this out! I did not know that this is possible - all the documentation about autovivification mentions it in the context of "chain" dereferencing, so I thought (or rather, "feeled") that it was connected to this operation exclusively. Is there any statement in the docs or the source somewhere that defines when autovivification will happen?

        Christian Lemburg
        Brainbench MVP for Perl
        http://www.brainbench.com

Re: A Not so Simple Append
by Fastolfe (Vicar) on Oct 03, 2000 at 01:41 UTC
    Hi Limo, this isn't an answer to your question here, but I'd like to recommend the Perl Cookbook to you. You're starting to move beyond some of the basics, and I think you would benefit a lot from this book, especially if you learn by example. I've been using Perl for years prior to getting ahold of this book, and it has dozens of tips and interesting Perl tidbits and shortcuts that will make your life a lot easier. A lot of the scenarios it covers are similar in scope and level of difficulty to some of your questions.

    Good luck.

      I would second Fastolfe's recommendation. The cookbook is well worth the money - I have found several suggestions there that have prevented me frompulling out my hair.
        Thank you, Maclir, and Fastolfe. Mostly, I appreciate the vote of confidence, as I'm sitting here, pulling my hair out. I do have this book, and refer to it (and others) frequently. You probably think that I'm an idiot after that statement, but let me explain. I am a network engineer for a very large ISP/E-business hosting provider. I have never programmed a line of code, prior to about a month ago. Frankly, I prefer net eng work. When I started this contract, I was very honest about what I knew and what I didn't know. And programming was specifically discussed during my interviews. Well, one day, my supervisor cxalls me in his office and says, "Steve, let's test out your programming skills." At this point I'm scratching my head. So, he gave me a spec, and I obsessed on it for a couple of days, and apparently he was impressed. Now, for some reason, I am "tool developer" for my group! My point is, that while I am learning at quite a rapid pace, I'm learning in sort of a fragmented fashion. In other words, I know bits and pieces, thus far. Most of the time, the examples in the Cookbook make sense to me. SOmetimes, they are close to what I need, and I just don't have the knowledge to manipulate the examples to do exactly what I need. Some of the books that I have, have exercises at the end of each chapter, to reinforce what has been taught in the preceding chapter. I wish that I had the luxury of methodically, reading each chapter and doing the exercises. But, unfortunately, since I am learning as I am producing production code, actual programming has to take precedence. I'll say it again; I am deeply indebted to you folks here, who have helped me out.
RE: A Not so Simple Append
by extremely (Priest) on Oct 03, 2000 at 03:41 UTC

    Obviously, you've already been helped but I'd like to point out a few things.

    @array is the array, if you want a single value from the array, it is better to use $array[0] rather than the @array[0] notation. Just so you know, doing that the second way is an array slice.
    See these alternatives:

    #your way. my $far = @array[0]; my $dev = @array[3]; #"better" way my $far = $array[0]; my $dev = $array[3]; # using array slices properly my ($far, $dev) = @array[0,3];

    Who knows, maybe that will help you out. =) Having it explained to me years ago sure did!

    --
    $you = new YOU;
    honk() if $you->love(perl)

      thanks, dude/dudette! it all helps!
RE: A Not so Simple Append
by Anonymous Monk on Oct 03, 2000 at 20:40 UTC
    I would suggest reading all of PRV into a hash of lists. Each city name is a hash key, each list contains all of the numbers associated with that city. After the whole file is parsed you can iterate through the hash and print out every item in its list.