Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: How to Order an Array's Elements to Match Another Array's Element Order

by ozboomer (Friar)
on Sep 17, 2019 at 12:40 UTC ( #11106297=note: print w/replies, xml ) Need Help??


in reply to How to Order an Array's Elements to Match Another Array's Element Order

Ok... Something to contemplate...

Firstly, some example program code:-

use warnings; use strict; use Data::Dumper; use Tie::IxHash; my %hash; tie %hash, "Tie::IxHash"; %hash = (); while (my $buf = <DATA>) { chomp($buf); my ($vitem, $project_info) = split(/,/, $buf); my ($project_name, $segment_info) = split(/\|/, my $project_info); my (@segments) = split(/;/, $segment_info); push(@{$hash{$project_name}{$vitem}}, @segments); } print Dumper(%hash); exit(0); # ----------- __DATA__ J_071117,BM:3|12.0-25.2;32.9-88.0 J_070424,BM:3|625-920;1017.905-1178 J_021212,BB:1|123-166;409-455 070526,SWT:1|53.160-59.320;77.720-86.120;370.800-416.800 070609,SWT:1|713.760-1159.200 070616a,SWT:1|0.0-652.0 070616b,SWT:1|401.40-461.800;483.160-490.640;503.400-595.200;602.440-6 +95.400;699.200-882.400 J_071019a,SWT:1|372.925-910.385;927.620-1038.830 J_071019b,SWT:1|268.15-808.330 J_071025,SWT:1|936.215-1659.635 071123_F,SWT:1|45.4550-81.665

...and the output it produces:-

$VAR1 = 'BM:3'; $VAR2 = { 'J_070424' => [ '625-920', '1017.905-1178' ], 'J_071117' => [ '12.0-25.2', '32.9-88.0' ] }; $VAR3 = 'BB:1'; $VAR4 = { 'J_021212' => [ '123-166', '409-455' ] }; $VAR5 = 'SWT:1'; $VAR6 = { '070526' => [ '53.160-59.320', '77.720-86.120', '370.800-416.800' ], '071123_F' => [ '45.4550-81.665' ], 'J_071019a' => [ '372.925-910.385', '927.620-1038.830' ], 'J_071025' => [ '936.215-1659.635' ], '070609' => [ '713.760-1159.200' ], '070616b' => [ '401.40-461.800', '483.160-490.640', '503.400-595.200', '602.440-695.400', '699.200-882.400' ], '070616a' => [ '0.0-652.0' ], 'J_071019b' => [ '268.15-808.330' ] };

As (I) expected/understood, the 'first-level' key is maintained in insertion order. However, subsequent (hash) key items are NOT in insertion order (which I did NOT expect/understand); array items ARE in insertion order.

Ultimately, I want to be able to refer to the hash in a form like:-

@{$hash{$project}{$vitem}}

...realizing that this can be problematic, given that I'm using a couple of different Perl versions and the "keys on reference is experimental at..." issue is (not) present in some cases... but one thing at a time...(!)

Effectively, do something like:-

for each project output "Project: ", project for each vitem in the current project output " VItem: ", vitem for each vitem segment output " Segment: ", segment endfor endfor endfor

...but if you looked at the output, the "VItems" would be in the original order they were shown in the __DATA__ block (within in each project).

Oh.. and something I should have explained earlier... Running all this with Perl v5.20.2, build 2001, under 32-bit Win8.1 OR Perl v5.18.1, under Linux Kernel 3.14.55 (Puppy Linux 32-bit v6.3.2).

Hopefully, this helps explain the context some...

Replies are listed 'Best First'.
Re^2: How to Order an Array's Elements to Match Another Array's Element Order
by hippo (Chancellor) on Sep 17, 2019 at 13:15 UTC

    With arrays for ordering instead of IxHashes:

    #!/usr/bin/perl use warnings; use strict; my %hash; my @projects; my %vitems; while (my $buf = <DATA>) { chomp($buf); my ($vitem, $project_info) = split(/,/, $buf); my ($project_name, $segment_info) = split(/\|/, $project_info); my (@segments) = split(/;/, $segment_info); push @projects, $project_name unless exists $hash{$project_name}; push @{$vitems{$project_name}}, $vitem; push(@{$hash{$project_name}{$vitem}}, @segments); } for my $proj (@projects) { print "Project: $proj\n"; for my $vi (@{$vitems{$proj}}) { print " VItem: $vi\n"; for my $seg (@{$hash{$proj}{$vi}}) { print " Segment: $seg\n"; } } } exit(0); # ----------- __DATA__ J_071117,BM:3|12.0-25.2;32.9-88.0 J_070424,BM:3|625-920;1017.905-1178 J_021212,BB:1|123-166;409-455 070526,SWT:1|53.160-59.320;77.720-86.120;370.800-416.800 070609,SWT:1|713.760-1159.200 070616a,SWT:1|0.0-652.0 070616b,SWT:1|401.40-461.800;483.160-490.640;503.400-595.200;602.440-6 +95.400;699.200-882.400 J_071019a,SWT:1|372.925-910.385;927.620-1038.830 J_071019b,SWT:1|268.15-808.330 J_071025,SWT:1|936.215-1659.635 071123_F,SWT:1|45.4550-81.665
Re^2: How to Order an Array's Elements to Match Another Array's Element Order
by tybalt89 (Parson) on Sep 18, 2019 at 04:46 UTC

    You could keep everything in the same hash :)

    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11106277 use warnings; my $order = '*order*'; my %hash; while( <DATA> ) { my ($vitem, $project, $segments) = /(\w+),(\w+:\d+)\|(.*)/; exists $hash{$project} or push @{$hash{$order}}, $project; exists $hash{$project}{$vitem} or push @{$hash{$project}{$order}}, $ +vitem; push @{$hash{$project}{$vitem}}, split /;/, $segments; } for my $project ( @{ $hash{$order} } ) { print "Project: $project\n"; for my $vitem ( @{ $hash{$project}{$order} } ) { print " Vitem: $vitem\n"; for my $segment ( @{ $hash{$project}{$vitem} } ) { print " Segment: $segment\n"; } } } __DATA__ J_071117,BM:3|12.0-25.2;32.9-88.0 J_070424,BM:3|625-920;1017.905-1178 J_021212,BB:1|123-166;409-455 070526,SWT:1|53.160-59.320;77.720-86.120;370.800-416.800 070609,SWT:1|713.760-1159.200 070616a,SWT:1|0.0-652.0 070616b,SWT:1|401.40-461.800;483.160-490.640;503.400-595.200;602.440-6 +95.400;699.200-882.400 J_071019a,SWT:1|372.925-910.385;927.620-1038.830 J_071019b,SWT:1|268.15-808.330 J_071025,SWT:1|936.215-1659.635 071123_F,SWT:1|45.4550-81.665

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2020-01-18 19:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?