Sorting a nested array (table) (alphabetically)

Discussion in 'Perl Misc' started by nstott1982, Sep 29, 2005.

  1. nstott1982

    nstott1982 Guest

    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 ];

    $DataTemp[0][0] = $ID;

    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
    nstott1982, Sep 29, 2005
    1. Advertisements

  2. nstott1982

    Paul Lalli Guest

    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";
    You are obviously not using warnings. Please read the posting
    guidelines for this group.
    I don't understand what this means. Can you provide some sample input
    and desired output?
    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
    perldoc -q sort
    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

    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
    Paul Lalli, Sep 29, 2005
    1. Advertisements

  3. nstott1982

    Neil Guest

    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/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

    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[0][0] being the number of rows


    [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

    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
    Neil, Oct 3, 2005
  4. nstott1982

    robic0 Guest

    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;

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

    robic0, Oct 4, 2005
  5. nstott1982

    rodan Guest

    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 ...
    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.
    It's better thought of as rows and fields,
    "columns" denote numeric, fixed width common type, byte oriented
    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.
    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]}

    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.

    rodan, Oct 4, 2005
  6. nstott1982

    Neil Guest

    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)
    Neil, Oct 4, 2005
  7. nstott1982

    robic0 Guest

    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],
    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->[$_] }

    Notation like [][][] will get you more screwed up in Perl than anything
    especially when using references and moreover anonymous array/hash
    This problem you are having is about the simplest problem in the world
    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.
    robic0, Oct 4, 2005
  8. nstott1982

    Neil Guest

    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

    if there is another way of doing this not using references of array
    could you please point me in that direction.
    Neil, Oct 5, 2005
  9. nstott1982

    Neil Guest

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

    Neil, Oct 5, 2005
  10. nstott1982

    Neil Guest

    /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.
    Neil, Oct 5, 2005
  11. nstott1982

    Paul Lalli Guest

    This statement, combined with...
    .... this statement, has just overloaded my irony meter.

    Paul Lalli
    Paul Lalli, Oct 5, 2005
  12. nstott1982

    Neil Guest

    paul i wasnt refering to you...

    your help is appriciated to. ;)
    Neil, Oct 5, 2005
  13. nstott1982

    Paul Lalli Guest

    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
    Paul Lalli, Oct 5, 2005
  14. nstott1982

    Neil Guest

    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.
    Neil, Oct 5, 2005
  15. You might be able to create a more positive image for yourself by adopting
    an effective posting style as explained in the posting guidelines.

    A. Sinan Unur, Oct 5, 2005
  16. nstott1982

    Neil Guest

    your guidlines dont help me learn how to explane thoughts in my head.
    Neil, Oct 6, 2005
  17. nstott1982

    Paul Lalli Guest

    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
    Paul Lalli, Oct 6, 2005

  18. So long!
    Tad McClellan, Oct 6, 2005
  19. 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.

    Jürgen Exner, Oct 12, 2005
  20. nstott1982

    Dr.Ruud Guest

    Dr.Ruud, Oct 12, 2005
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.