Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can anyone help me this? 2

Status
Not open for further replies.

michael12

Programmer
Sep 26, 2002
25
0
0
US
I have a text file "test.txt":
----------
name age address
abc1 20 city1
abc2 15 city2
abc3 45 city3
abc4 19 city4
----------

How can I open this file and print out the new one which is sorted by age? Thanks.
 
Quick and dirty, here's how I would do it.
Code:
open IN, "test.txt" or die "IN: $!";
# since you have to sort the lines
# you need them all read into an array
my @lines = <IN>;
close(IN);
# Pull off field headers and save for output
my $fields = shift @lines;
# Efficient sorting method
my @sorted =
    map { $_->[0] }
    sort { $a->[1] <=> $b->[1] }
    map { [ $_ , (split)[1] ] } @lines;

open OUT, &quot;> sorted.txt&quot; or die &quot;OUT: $!&quot;;
# print lines to new file, including the header fields
print OUT for $fields, @sorted;
close (OUT);
You could sort the lines in a single sort call but it would cost you a split each time an element in the array is accesed for a comparison, which is more than once. Using the map/sort/map, the split is only called once for each element.

jaa
 
This is a good script but I am lost on the &quot;map&quot; part. I did a &quot;perldoc -q map&quot; but it didnt give me much on what it does. I can get a book on it but just one question:

[tt]
map { $_->[0] }[/tt]

This part is fetching the just the name field values (in first column)?
What is the purpose of fetching the first column to start?
 
You read the map/sort/map is from the bottom up. Its actually all one line but is broken up for readability. Do a search on google for schwartzian transform to read about this.

'[tt]perldoc -f map[/tt]' will be more informative. '-f' is the function lookup flag, vs '-q', which is the faq lookup flag.

the bottom map
[tt]map { [ $_ , (split)[1] ] } @lines;[/tt]
maps each element of @lines to a two-element anonymous array consisting of the element itself as the first value and the age as the second value. The [tt](split)[1][/tt] is equivalent to
[tt]{ @fields = split /\s+/, $_; $fields[1] }[/tt], which picks off the age.
The data structure would look like
Code:
@unnamed_array = (  [ &quot;abc1   20   city1&quot;, 20 ],
                    [ &quot;abc2   15   city2&quot;, 15 ],
                    [ &quot;abc3   45   city3&quot;, 45 ],
                    [ &quot;abc4   19   city4&quot;, 19 ],
                  );
Then
sort { $a->[1] <=> $b->[1] }
sorts these anonymous arrays by the second value ([tt]$a->[1][/tt], the standalone age). The sorted anonymous arrays are then fed to the top map
map { $_->[0] }
and only the original element is selected and put into @sorted.

This is more efficient than the alternative of
Code:
my @sorted = sort { (split /\s+/, $a)[1] <=> (split /\s+/, $b)[1] } @lines;
in which split is called several times for each element during the sort.

jaa
 
Thanks for your knowledge and explanation! I now understand this alot better.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top