in reply to Fence vs. Posts
This feels like an XY Problem to me. Why create lists with a bunch of duplicates, when you can just walk through @trip, looking at the current item and the next? Also, NetWallah made an excellent point about graphs - although in this case, if your "trips" are always linear, you don't really need a graph. I don't quite understand your question about the @states array - why not build the hash with city/state information first? So if you could explain the background of your question some more, we could probably suggest even better solutions.
Here's how I might have approached it - as you can see, no arrays with duplicate elements involved. In the "alternative" I go a step further and make the elements of @trip references to the anonymous hashes. So that I don't lose the city name, I store it in those hashes as well. This has the advantage that you know beforehand that all your cities are spelled correctly, and all the city information is available via the elements of the @trip array (notice how I no longer need %cities in the loop).
use warnings; use strict; use Data::Dump; my @trip = ("Chicago", "Saint Looey", "Joplin", "OKC", "Amarillo", "Gallup", "Flagstaff", "Winona", "Kingman", "Barstow", "San Bernandino", "LA"); my %cities = ( "Amarillo" => { state => "TX" }, "Barstow" => { state => "CA" }, "Chicago" => { state => "IL" }, "Flagstaff" => { state => "AZ" }, "Gallup" => { state => "TX" }, "Joplin" => { state => "MO" }, "Kingman" => { state => "AZ" }, "LA" => { state => "CA" }, "OKC" => { state => "OK" }, "Saint Looey" => { state => "MO" }, "San Bernandino" => { state => "CA" }, "Winona" => { state => "AZ" }, ); for my $i (0..$#trip-1) { my ($from,$to) = @trip[$i,$i+1]; print "$from, $cities{$from}{state} to $to, $cities{$to}{state}", $cities{$from}{state} ne $cities{$to}{state} ? " - Mann Act!" : (), "\n"; } print "\n##### Alternative #####\n"; $cities{$_}{city} = $_ for keys %cities; $_ = $cities{$_}//die("bad city $_") for @trip; dd \%cities, \@trip; for my $i (0..$#trip-1) { my ($from,$to) = @trip[$i,$i+1]; print "$from->{city}, $from->{state} to $to->{city}, " ."$to->{state}", $from->{state} ne $to->{state} ? " - Mann Act!" : (), "\n"; }
Output:
Chicago, IL to Saint Looey, MO - Mann Act! Saint Looey, MO to Joplin, MO Joplin, MO to OKC, OK - Mann Act! OKC, OK to Amarillo, TX - Mann Act! Amarillo, TX to Gallup, TX Gallup, TX to Flagstaff, AZ - Mann Act! Flagstaff, AZ to Winona, AZ Winona, AZ to Kingman, AZ Kingman, AZ to Barstow, CA - Mann Act! Barstow, CA to San Bernandino, CA San Bernandino, CA to LA, CA ##### Alternative ##### do { my $a = { "Amarillo" => { city => "Amarillo", state => "TX" }, "Barstow" => { city => "Barstow", state => "CA" }, "Chicago" => { city => "Chicago", state => "IL" }, "Flagstaff" => { city => "Flagstaff", state => "AZ" }, "Gallup" => { city => "Gallup", state => "TX" }, "Joplin" => { city => "Joplin", state => "MO" }, "Kingman" => { city => "Kingman", state => "AZ" }, "LA" => { city => "LA", state => "CA" }, "OKC" => { city => "OKC", state => "OK" }, "Saint Looey" => { city => "Saint Looey", state => "MO" }, "San Bernandino" => { city => "San Bernandino", state => "CA" }, "Winona" => { city => "Winona", state => "AZ" }, }; ( $a, [ $a->{"Chicago"}, $a->{"Saint Looey"}, $a->{"Joplin"}, $a->{"OKC"}, $a->{"Amarillo"}, $a->{"Gallup"}, $a->{"Flagstaff"}, $a->{"Winona"}, $a->{"Kingman"}, $a->{"Barstow"}, $a->{"San Bernandino"}, $a->{"LA"}, ], ); } Chicago, IL to Saint Looey, MO - Mann Act! Saint Looey, MO to Joplin, MO Joplin, MO to OKC, OK - Mann Act! OKC, OK to Amarillo, TX - Mann Act! Amarillo, TX to Gallup, TX Gallup, TX to Flagstaff, AZ - Mann Act! Flagstaff, AZ to Winona, AZ Winona, AZ to Kingman, AZ Kingman, AZ to Barstow, CA - Mann Act! Barstow, CA to San Bernandino, CA San Bernandino, CA to LA, CA
Anyway, to answer your original question, the idiom I would have used is map {@arr[$_,$_+1]} 0..$#arr-1. Note that using map purely for its side-effects is considered bad style by some, and usually a for statement modifier is also a bit easier to read. <update> To clarify, I mean that using map purely for its side effects as you've done in your original code - what I'm doing here does not fall into that category (see also my reply lower down in the thread). </update> The reason your creation of the %info hash isn't working in the original code is that you're not dereferencing the pairs.
use warnings; use strict; use Data::Dump; use List::Util 'pairs'; use List::MoreUtils 'mesh'; my @trip = ("Chicago", "Saint Looey", "Joplin", "OKC", "Amarillo", "Gallup", "Flagstaff", "Winona", "Kingman", "Barstow", "San Bernandino", "LA"); my @states = ("IL", "MO", "MO", "OK", "TX", "TX", "AZ", "AZ", "AZ", "CA", "CA", "CA" ); my @legs = map {@trip[$_,$_+1]} 0..$#trip-1; printf "%15s to %-15s\n", $_->[0], $_->[1] for pairs @legs; my %info; $info{$_->[0]}{state} = $_->[1] for pairs mesh @trip, @states; dd \%info; __END__ Chicago to Saint Looey Saint Looey to Joplin Joplin to OKC OKC to Amarillo Amarillo to Gallup Gallup to Flagstaff Flagstaff to Winona Winona to Kingman Kingman to Barstow Barstow to San Bernandino San Bernandino to LA { "Amarillo" => { state => "TX" }, "Barstow" => { state => "CA" }, "Chicago" => { state => "IL" }, "Flagstaff" => { state => "AZ" }, "Gallup" => { state => "TX" }, "Joplin" => { state => "MO" }, "Kingman" => { state => "AZ" }, "LA" => { state => "CA" }, "OKC" => { state => "OK" }, "Saint Looey" => { state => "MO" }, "San Bernandino" => { state => "CA" }, "Winona" => { state => "AZ" }, }
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Fence vs. Posts
by BillKSmith (Monsignor) on Jun 08, 2018 at 14:53 UTC | |
by haukex (Archbishop) on Jun 10, 2018 at 09:55 UTC | |
|
Re^2: Fence vs. Posts
by rodinski (Novice) on Jun 09, 2018 at 15:04 UTC | |
by Veltro (Hermit) on Jun 09, 2018 at 15:59 UTC | |
by rodinski (Novice) on Jun 14, 2018 at 13:15 UTC |