Sorting a nested array (table) (alphabetically)


N

nstott1982

hello all,

im not to great a perl but learning as i go along.

bigest problem i have hit is sorting a nested array, i would appriciate
any help given.

here is the code i use to read the file into the array


$ID = 1;
open (InData, $DataStore);
while ($CurrentLine = <InData>) {
@DataTempA = split(/¤/,$CurrentLine);
@DataTemp[$ID] = [ @DataTempA ];
$ID++;

}
$DataTemp[0][0] = $ID;
close(InData);


i would like to sort by different columns (@DataTemp[Row][Col])

i cant seem to find anything on the net which i can understand,

im not expecting anyone to just write me the code that will work
(although would be sweet) but just a point in the right direction would
be good

Thanx in advance
 
Ad

Advertisements

P

Paul Lalli

bigest problem i have hit is sorting a nested array, i would appriciate
any help given.

here is the code i use to read the file into the array


$ID = 1;
open (InData, $DataStore);

Always check the return value of open(). Currently, you have no way of
knowing whether or not $DataStore was successfully opened.

open InData, '<', $DataStore or die "Could not open $DataStore: $!\n";
while ($CurrentLine = <InData>) {
@DataTempA = split(/¤/,$CurrentLine);
@DataTemp[$ID] = [ @DataTempA ];

You are obviously not using warnings. Please read the posting
guidelines for this group.
$ID++;

}
$DataTemp[0][0] = $ID;
close(InData);


i would like to sort by different columns (@DataTemp[Row][Col])

I don't understand what this means. Can you provide some sample input
and desired output?
i cant seem to find anything on the net which i can understand,

Perhaps you could show us what you did find, and let us know how you
were unable to understand it, so that we could clarify it for you?

Have you read Perl's built in documentation for sort?
perldoc -f sort
http://perldoc.perl.org/functions/sort.html
perldoc -q sort
http://perldoc.perl.org/perlfaq4.html#How-do-I-sort-an-array-by-(anything)?
im not expecting anyone to just write me the code that will work
(although would be sweet) but just a point in the right direction would
be good

In general, you provide sort with a block which compares two elements
of your list (which Perl assigns to $a and $b), and returns -1 if $a
should come first, 1 if $b should come first, and 0 if it doesn't
matter.

In your case, $a and $b would be array references (as each element of
the overall array is an array reference). It's up to you to decide how
to determine which of two array references should come first.

Without knowing exactly how you want your 2-d array sorted, however,
it's hard to give an example.

Paul Lalli
 
N

Neil

if the script fails to work the file could not be opened. (it did have
a die command in but i tried to change it so i could run another part
of the script if it didnt open but i was doing something wrong so
deleted it and havent put die back)

i get my warning from the perl editor im using

here is a snip from the data file on how it is stored

P/001¤5.08¤Order Requisition.¤-¤Y¤3 Years¤Accounts Admin¤¤
P/002¤5.07¤Request for Subcontractor Approval¤Jul-98¤Y¤3
Years¤Purchase Control¤P_002.dot¤
P/003¤5.07¤Supplier Quality System Assessment
Questionnaire¤Apr-03¤Y¤3 Years¤Quality Control¤P_003.pdf

the above information is split using ¤ into a nested array forming a
table

i want to be able to sort the columns e.g the data file is currently in
order by the first column (Form Number) i want to be able to sort by
Title instead (Col 3) or Ref (Col2)

ive seen the links you have given me above but i cant get my head round
on how im gonna impliment it into my code, seem to understand working
examples better that normal help examples

note. i dont want to resort the data in the file just the data in the
array so when it is outputed to screen its in the selected order

note2. $TempData[0][x] $TempData[1][x] do not want to be sorted as they
contain the table headers & other setting/info i require for the page
formatting. i want to sort between $TempData[2][x] and
$TempData[$TempData[0][0]][x]

$TempData[0][0] being the number of rows

and

[x] being the whole row ie [0] to [8]

ive got a working search function just annoying me trying to understand
how i can get this sort function to work. once thats is done my script
is almost complete just need to tidy & add some error checking etc and
ajust how it reads from the file so i can have different number of
columns.

hope this hasnt confused everyone some more its quite hard to type in
this tiny box (maybe opera?) oh now ive previewd it and edited again
its gone to a nice big eddit box ummm why couldnt it do this first
 
R

robic0

Neil said:
if the script fails to work the file could not be opened. (it did have
a die command in but i tried to change it so i could run another part
of the script if it didnt open but i was doing something wrong so
deleted it and havent put die back)

i get my warning from the perl editor im using

here is a snip from the data file on how it is stored

P/001¤5.08¤Order Requisition.¤-¤Y¤3 Years¤Accounts Admin¤¤
P/002¤5.07¤Request for Subcontractor Approval¤Jul-98¤Y¤3
Years¤Purchase Control¤P_002.dot¤
P/003¤5.07¤Supplier Quality System Assessment
Questionnaire¤Apr-03¤Y¤3 Years¤Quality Control¤P_003.pdf

the above information is split using ¤ into a nested array forming a
table

TempData is the container, it only holds references.
Make sure the fields line up, then do sometthing like this:

use sort 'stable';

my @TempData = ();
.... Read data loop
my $aref = [];
@{$aref} = split(....);
push (@TempData, $aref);
.... End loop

.... ascending sort by col 5 (numeric) then by 2 (alpha)
@TempData = sort {$a->[5] <=> $b->[5]} @TempData;
@TempData = sort {$a->[2] cmp $b->[2]} @TempData;
.... print something
for (@TempData) {
print "$_->[2] $_->[5] \n";
}

.... descending sort by col 5 (numeric) then by 8 (alpha)
@TempData = sort {$b->[5] <=> $a->[5]} @TempData;
@TempData = sort {$b->[8] cmp $a->[8]} @TempData;

etc...
You can generalize and make utility functions.
Try not to use Fortran script notation when dealing with arrays of
records !!

gluck
 
R

rodan

I'm testing out a name change with Agent, my browser.
So if it doesen't work, I'm that last guy robic.
-------------------------------------------------------------
I just want to post some follow up comments for you ...
P/001¤5.08¤Order Requisition.¤-¤Y¤3 Years¤Accounts Admin¤¤
P/002¤5.07¤Request for Subcontractor Approval¤Jul-98¤Y¤3
Years¤Purchase Control¤P_002.dot¤
P/003¤5.07¤Supplier Quality System Assessment
Questionnaire¤Apr-03¤Y¤3 Years¤Quality Control¤P_003.pdf

the above information is split using ¤ into a nested array forming a
table
For best results try not to think in terms of "nested".
What you have is an array of records (or structures).
Thats what a "table" is.
i want to be able to sort the columns e.g the data file is currently in
order by the first column (Form Number) i want to be able to sort by
Title instead (Col 3) or Ref (Col2)
It's better thought of as rows and fields,
"columns" denote numeric, fixed width common type, byte oriented
ordinals.
ive seen the links you have given me above but i cant get my head round
on how im gonna impliment it into my code, seem to understand working
examples better that normal help examples

note. i dont want to resort the data in the file just the data in the
array so when it is outputed to screen its in the selected order
Sorting large amounts of data does not mean "moving" that data around.
Having a pre-defined pointer (in C) or a reference (in Perl)
means you don't actually "move" the data but just collect the pointer
or reference in a different way so that when you want to access
that data all you have to do is to access the arranged pointers
or references to print the real data in a sorted order.
In database terms, this is called an index. So the "real" data
stays put and never moves. You just manipulate arrays of references
that mirror how the data relates to itself.
Comparing data elements in my example, just manipulates/re-arranges
the containing array of references "to" the data.... it does not
actually move the data around. Thats why its so fast.
note2. $TempData[0][x] $TempData[1][x] do not want to be sorted as they
contain the table headers & other setting/info i require for the page
formatting. i want to sort between $TempData[2][x] and
$TempData[$TempData[0][0]][x]

$TempData[0][0] being the number of rows
It looks like you have a header you want to embedd in the table
itself. On the array sort example I gave you above, I purposely
left out the fact that you could have sorted the containing
array of references, @TempData starting and ending on any element
like this:

@TempData[$start..$end] = sort {$a->[$somefield] cmp $b->[$somefiled]}
@TempData[$start..$end];

Instead, make a containing header, that holds all the info on
the "table". Its not necessary to track the number of fields
as @{$aref}-1 will give the last element for boundry checking.

A known element of the header could be a "reference" to the
actual data array so that if you write a specialized function to do
your sorts, just pass a reference to the containing header,
along with info on the prioritized, variable number of fields
you want to sort. Really though, most containing headers
should be hashes so you can easilly access the "named" table.

- header as an array:
@HeaderArray = ();
$HeaderArray[0] = "Table Name";
$HeaderArray[1] = \@TempData;
$HeaderArray[2] = another known important table info
.... then calling MySpecialArrayHeaderTableSort (\@HeaderArray,...);
- header as a hash:
%HeaderHash = ();
$HeaderHash{'TableName'} = "Table Name";
$HeaderHash{'Data'} = \@TempData;
$HeaderHash{'ExtraInfo'} = another known important table info
.... or calling MySpecialHashHeaderTableSort (\%HeaderHash,....);

The "header" container now contains all the info.
You could actually now control a group of variable tables via
another container:

@AllTables = (\@HeaderArray1, \%HeaderHash1,....);
This is just an array of "references".

Hope this helps you. I didn't go into a much more complicated
area called compound structures.
Its always a good idea to keep a greater than 2 dimentioned
array "homogenous" and NOT try to imbedd anything which
makes it "non-square". Always factor out to a new level
if that is what you need to do.

Let me know if you need any more help.

gluck
 
N

Neil

ok mind blow :p

ive tried implimenting what you have said above in the way i get the
data into the array but cant seem to get that working.

would i be able to email you the whole code? (might help you understand
whats going on in my head and how my coding skillz work/dont)

all what i know if self taught on a learn as i require method so there
is alot of commands i have not come accross that would prob save time
(mine & cpu) but untill i hit a problem which will guide me to the
command i may never learn it.

ive just had to change alot of the script on how it gets form data
because i wanted it to upload a file but couldnt with the method i was
using. (new commands come to light)

i think one of my main probem is i dont fully understand the sort
command mainly "{$a->[$somefield] cmp $b->[$somefiled]}"

nor do i really understand how ive got the data into the array (other
that ive split the data into one array [giving me the fields] then put
that array inside another array so i get records/columns)
 
Ad

Advertisements

R

robic0

No don't send me any code, I already know your problem.
I doubt you have tried anything I said or any code snipets above.
To get it to work is just to cut and paste. Your file read method
for getting the records into a containter are ok. So your real
problem is you just don't understand what it is you did
otherwise you would know whats going on with sort.

I don't know why you seem to want to save the amount of
records read in. The size of the array IS the number of
records read in less the elements you want to use to store
header info.

$array_size = @TempData;
$last_element = $array_size - 1;

you want to sort just the data elements on some record field.

my $last_element = @TempData - 1;
my $hdr_ref = $TempData[1];

MySort (\@TempData, 2, (8, 5, 2));

# print some records
print "\nSort by fields: $hdr_ref->[8], $hdr_ref->[5],
$hdr_ref->[2]\n-------------\n";
for (@TempData[2..$last_element]) {
print "Name:\t$_->[2]\nAddr:\t$->[4]\nPhone:\t$_->[8]\n";
}

MySort (\@TempData, 2, 6);
# print some records
print "\nSort by fields: $hdr_ref->[6]\n-------------\n";
for (@TempData[2..$last_element]) {
print "Name:\t$_->[6]\n";
}


sub MySort {
my ($Array_ref, $data_start_element, @var_fields_array) = @_;
# insert error check for variables
my $last_element = @$Array_ref - 1;

for (@var_fields_array) {
@{$Array_ref}[$data_start_element..$last_element] = sort {
$a->[$_] cmp $b->[$_] }
@{$Array_ref}[$data_start_element..$last_element];
}
}

Notation like [][][] will get you more screwed up in Perl than anything
else
especially when using references and moreover anonymous array/hash
ones.
This problem you are having is about the simplest problem in the world
for
a programmer. So I am asuming since there is absolutely no value to
manipulating data in this way that is a "homework" exercise.

You should re-read the documentation on arrays and understand it
entirely. Perl is NOT fortran. Lose any fortran code you have when
trying to write stuff in Perl.
 
N

Neil

This problem you are having is about the simplest problem in the world
for a programmer. So I am asuming since there is absolutely no value to

manipulating data in this way that is a "homework" exercise.

^^^ there is a better way???

just going to try what you said above, ive spent 6 hours reading perl
docs so far today.

the value is, i get a table sorted by the column i want printed to the
screen.

if there is another way of doing this not using references of array
could you please point me in that direction.
 
N

Neil

/me runs around flapping his hands \o/ -o- \o/

well ive got the it working (copy, paste & little typo correction)

robic: i really dont know how to thankyou dude, never managed to get so
much help before (the work done for me) still dont fully understand
whats going on but it works :)

most people just give you one line of code then tell you to read the
f-ing manual (from experiance)


all i need todo now is add alot of error checking, tidy up, make its
work with multi data files.

then im gonna turn use strict on and break it :p

Thankyou very much robic you help has been greatly appriciated.
 
P

Paul Lalli

Neil said:
never managed to get so
much help before (the work done for me) still dont fully understand
whats going on but it works :)

This statement, combined with...
most people just give you one line of code then tell you to read the
f-ing manual (from experiance)

.... this statement, has just overloaded my irony meter.

Paul Lalli
 
Ad

Advertisements

P

Paul Lalli

Neil said:
paul i wasnt refering to you...

No, I didn't think you were. Of course, since you keep not quoting any
attributes or context, it could have been difficult to know for sure...

I was simply pointing out the irony that you believe the "most help"
you've gotten was for someone to write a program for you, rather than
being asked to read some documentation, while simultaneously admitting
that you don't understand how the program works at all.

You clearly have some definition of the word "help" with which I was
previously unfamiliar.

Paul Lalli
 
N

Neil

i should have used the words "Explaned Example" instead of help

lost of stuff i wanna say but im not the best at writing stuff down. im
just gonna shut my fingers so not to insult anyone or make my self look
anymore stupid than i already have.
 
A

A. Sinan Unur

lost of stuff i wanna say but im not the best at writing stuff down. im
just gonna shut my fingers so not to insult anyone or make my self look
anymore stupid than i already have.

You might be able to create a more positive image for yourself by adopting
an effective posting style as explained in the posting guidelines.

Sinan
 
Ad

Advertisements

P

Paul Lalli

Neil said:
your guidlines dont help me learn how to explane thoughts in my head.

Perhaps not, but they would help you:
1) Learn how to post a reply correctly, including quoting context of
the message you're replying to, so that you don't end up in any more
killfiles than you already have.
2) Learn to give, *at the least*, actual sample input and actual
desired output, so we can see exactly what it is you want to do,
without needing to interpret the thoughts in your head.

Paul Lalli
 
J

Jürgen Exner

Neil said:
your guidlines dont help me learn how to explane thoughts in my head.

Well, as incredible as it sounds actually they do.

You may have missed the discussion some weeks ago where someone mentioned
that at a university there was an iron rule that before a student was given
any help from the help desk he had to explain his problem to the teddy bear
that was sitting in the office.
A very large percentage of problems were solved by the teddy bear simply
because the student was forced to organize his thoughts and to explain his
problem in a coherent, understandable way, even if only a teddy bear was
listening. This lead to himself understanding the problem better and very
often to identify the issue and find a solution on his own.

We don't have a teddy bear here, but the posting guidelines are meant to
"force" you to organize your own thoughts first. Very often this will result
in you finding a solution yourself. And if not at least a coherent and
well-written text will help other people to actually understand what you are
talking about.

jue
 
Ad

Advertisements


Top