Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^5: Reorganizing the content of a file

by Laurent_R (Canon)
on Dec 20, 2018 at 09:06 UTC ( [id://1227511]=note: print w/replies, xml ) Need Help??


in reply to Re^4: Reorganizing the content of a file
in thread Reorganizing the content of a file

Hi ovedpo15,

The only problem to keep the original order of the input is that the data structure used in my solution, a hash, does not have a defined order. However, the solution is fairly easy: we only need to keep track of the original order one way or another.

One possible way to do that is to add an array (@ranks) as an auxiliary data structure when reading the file and then to loop over the array when preparing the output:

use strict; use warnings; use feature 'say'; my (%tree, @ranks); while (<DATA>) { chomp; my ($id, $pid, $name) = split /,/; $tree{$id} = {pid => $pid, name => $name}; push @ranks, $id; } for my $id (@ranks) { my @parent_list; my $temp_id = $id; while (exists $tree{$temp_id}) { push @parent_list, $tree{$temp_id}{name}; $temp_id = $tree{$temp_id}{pid}; } say join ",", @parent_list; } __DATA__ 15,10,name3 10,#,name1 12,10,name2 5,12,name4 8,5,name5
which produces the following output:
$ perl test_ranks.pl name3,name1 name1 name2,name1 name4,name2,name1 name5,name4,name2,name1
The solution you contemplated in your question is also relatively easy, except for the syntax used to sort the records according to the ranks, which may be regarded as a bit complicated for a Perl beginner. Here, I have added a rank field into the records and then sort the id's in accordance to the rank:
use strict; use warnings; use feature 'say'; my (%tree); while (<DATA>) { chomp; my ($id, $pid, $name) = split /,/; $tree{$id} = {pid => $pid, name => $name, rank => $.}; } for my $id (sort { $tree{$a}{rank} <=> $tree{$b}{rank} } keys %tree) { my @parent_list; my $temp_id = $id; while (exists $tree{$temp_id}) { push @parent_list, $tree{$temp_id}{name}; $temp_id = $tree{$temp_id}{pid}; } say join ",", @parent_list; } __DATA__ 15,10,name3 10,#,name1 12,10,name2 5,12,name4 8,5,name5
which produces the same output as before.

Another possible way might be to read the input file again to get the id's in the proper order, but I wouldn't recommend that as that would be less efficient.

You may also take a look at the Hash::Ordered module on the CPAN, which implements a hash data structure with a builtin order.

Update: Fixed a typo: s/reparing the output/preparing the output/.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-25 17:33 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found