gatornek has asked for the wisdom of the Perl Monks concerning the following question:

I pray to the monastary for forgiveness. I am sorry for sounding pompous in my request for wisdom at 3am last night. Again, I am brand new to perl AND this site. I would never want anyone to do my homeowrk for me and I appreciate the insights that were given (although, I do have trouble understanding the syntax of much of the code). Anyway, I will try to be more thorough in my postings and not lead the monastary into believing they are "doing my homework for me". This snippet of code (the sort) is part of a much bigger project that I've left for the last minute (the script, that is, not the project). Anyway, I do have some pseudocode that I can share so that I can get the proper syntax on this "array sort" correct. Again, if this were Java, I'd know exactly how to handle this (if I was a racecar driver and Perl was a Maserati as I hear it can be, I'd still be idling). But, here goes nothing (remember, this is pseudocode):
sub mysort { chomp(@entries = <STDIN>); foreach $indexofleast (@entries) { $indexofleast = $firstelement; foreach $counter (@entries) { if ($counter lt $indexofleast) { $indexofleast eq counter; } if ($indexofleast ne $firstelement) { $temp = $firstelement; $firstelement = $indexofleast; $indexofleast = $temp; } } } }
I hope you all can see what I'm TRYING to do here. Basically I want to start at the beginning of an array, find the smallest value; if that value is not equal to the first value then I want to swap them, go on to the next sequential value in the array and iterate again until I have the array sorted from smallest (left) to largest (last). Again, I hope this message makes me sound less pompous than before and hope that I will be taken seriously in future attempts to "seek wisdom".

Replies are listed 'Best First'.
On capricious instructor mandates
by merlyn (Sage) on Feb 05, 2003 at 17:12 UTC
    And again, you'll get roughly the same answers. If you aren't using the built-in sort, you should be. And if you were told you can't, you don't need our help: you need the help of the person placing artificial restrictions on your Perl code, because you aren't coding in Perl any more. This site is about best-practices Perl code (and the culture surrounding it), not about capricious instructor mandates.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: Tedious array sort revisited
by hardburn (Abbot) on Feb 05, 2003 at 17:18 UTC

    Are you doing the sort on numeric data or strings? If so, you need to use '==' instead of 'eq', '!=' instead of 'ne', and '<' insetad of 'lt'. Or was that just part of the psedocode style?

    Also, your comments seem to indicate you're showing how to do a sort in Perl for academic reasons. If not, you should just use sort instead.

    ----
    Invent a rounder wheel.

Re: Tedious array sort revisited
by boo_radley (Parson) on Feb 05, 2003 at 18:39 UTC
    It sounds like a bubble sort. If you really can't use perl's sort for some reason ("capricious instructor mandates", getting a feel for perl's array operators, insanity, etc.), then you should at least know that it's quite easy to swap two values in an array with each other :
    ($array [$element_one], $array [$element_two]) = ($array [$element_two], $array [$element_one])

    you should also consult perlop to see how <=> and cmp work, which can considerably reduce the amount of code needed to write your own sorting mechanism.

    update


    I really think this would have a different outcome if we could see what the actual assignment is. Something's not being communicated correctly. I'm not advocating that the assignment be posted, of course, but this isn't going well for anyone.

      It is certainly not a "classic" bubble-sort but a curious mix of elements of an exchange sort (namely the swapping of the current record with the smallest remaining record) and an inverted type of insertion sort (namely finding the next smallest record and putting it directly in its place)

      None of these sorts are known to be fast or efficient and by combining them you probably get the worst elements of both.

      If this is homework, it is bad homework. I would never suggest a student to implement such a bad algorithm.

      To know more about sorting in general, one could do worse than read Don Knuth's "The Art of Computer Programming - Vol. 3 - Sorting and Searching".

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Tedious array sort revisited
by Enveigler (Initiate) on Feb 05, 2003 at 17:31 UTC

    You say you could do this in Java. I suggest you write it in Java. When it's working, translate the java syntax into perl as far as you can. When you get stuck, post the Java code and your attempted translation hilighting the lines your having trouble with. You might then get assistance in correcting those lines.

    It's good to understand how things work, and sorts are often used for this purpose when learning.

Re: Tedious array sort revisited
by no_slogan (Deacon) on Feb 05, 2003 at 17:41 UTC

    It seems to me that you want to do this in a perlish way, and that is why you are trying to do it with a foreach loop. However, foreach (@entries) is the wrong type of loop to use for sorting @entries. It can be done, but you're trying to pound a square peg into a round hole. Why? foreach goes through each element of an array, but it doesn't tell you where in the array the elements are located. A sorting routine, by its nature, needs to have at least some information about the location in the array of the elements it's comparing.

              foreach $counter (@entries)

    It's a good idea to use correct names for your variables, lest you confuse yourself. The loop variable in a foreach loop is not a counter, unless the array you're iterating over happens to be a counting sequence.

      Thank you for your help. I WAS trying to find a way to use the power of the foreach structure, but you showed me the error of my ways. Would it be better to say something like this:
      for (i = 0, i =< @#entries, i++) { $indexofleast = i; for (j = 1, j =< @#entries, j++) { if (@entries[j] lt @entries[i]) { $indexofleast = j; } if ($indexofleast != i) { $temp = @array[j]; $@array[j] = $@array[i]; $@array[i] = $temp; } } }
      Thanks for anymore help I can get. I stress that I am brand new to perl (so I'm really not sure if I'm using the @# operator correctly). This is supposed to work on single character strings and sort them.

        Close. I think you want $#entries, $array[i] and $array[j].

Re: Tedious array sort revisited
by perrin (Chancellor) on Feb 05, 2003 at 18:41 UTC
    sub mysort { chomp(my @entries = <STDIN>); return sort @entries; }
    If you don't understand how sort() works, you can read more about it here. If you think sort() is not appropriate to use here, you'd better explain yourself.
      I know that Perl is supposed to make the routine easy, but I'm specifically supposed to implement a sort subroutine without using any built in perl functions.

        Get thee to your nearest bookstore and get a copy of the wolf book (ISBN ISBN 1565923987), which has an entire chapter on sorting in perl without resorting to sort().

        If you have to re-invent the wheel, then please do yourself a favour and use some more efficient algorithm, e.g. a Quicksort or a Shell-sort.

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law