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

my @animals = ("frog", "toad", "snake", "grasshopper", "bird");


my @sorted_animals = (sort @animals); print "@sorted_animals"; # prints with spaces AND is sorted print sort "@animals"; # prints with spaces but doesn't sort print sort @animals; # sorts but doesn't have spaces print sort(@animals); # sorts but doesn't have spaces print sort("@animals"); # prints with spaces but doesn't sort print (sort("@animals")); # prints with spaces but doesn't print (sort(@animals)); # sorts but doesn't have spaces
I've been playing a little with arrays, as you can tell..but doesn't that look weird to anyone else? You can either sort without spaces or you can print "@array" and lose the sort. The only exception I found was when you store the sorted array in a different array and print that instead.

Is there a way to print a sorted array with spaces without making a new array?

Replies are listed 'Best First'.
Re: array sorting
by Caron (Friar) on Jan 29, 2004 at 07:05 UTC
Re: array sorting
by davido (Cardinal) on Jan 29, 2004 at 07:37 UTC
    I wanted to also follow-up explaining what each of the syntaxes you've used in your original post are actually doing. Since they each compile, and many do different things, some explanation is probably in order.

    The first one:

    my @sorted_animals = ( sort @animals ); print "@sorted_animals";

    This sorts @animals. sort then populates a list, and assigning the list to @sorted_animals.

    print sort "@animals";

    @animals is interpolated inside double-quotes. But the double-quotes form a single string filled with the contents of @animals. So you're just sorting a single string, not a list of strings. sort only acts on lists, not on the contents of a string.

    print sort @animals;

    Here sort is sorting the contents of @animals, returning a list of the contents of @animals, in sorted order. Here, the $, list separator comes into effect, which defaults to no space, so that's what you get.

    print sort(@animals);

    Same as the previous example. The parantheses in this case just disambiguate the boundries of the sort function's parameters.

    print sort("@animals");

    This is the same as print sort "@animals";. No significant difference in this case.

    print (sort("@animals"));

    This is the same as print sort "@animals";. You've just disambiguated the boundries of the parameter lists for sort and print.

    print (sort(@animals));

    This is the same as print sort @animals; but with parenthesis around the parameter lists of sort and print. Again, this may lend clarity, and in some situations is a necessary way of bounding the parameter lists. But in this case is just a redundant syntax.

    Just keep in mind, and array interpolated inside of a string gives you just a big string, not a lot of little ones.


    Dave

Re: array sorting
by davido (Cardinal) on Jan 29, 2004 at 07:02 UTC
    Don't rely on that sort of thing (string interpolation, etc). Here's a good way:

    print join(" ", sort @animals);

    Or you could do this:

    { local $, = " "; print sort( @animals ); }

    The latter method has the advantage of not creating a temporary second copy of the array in the form of a string as the result of join. This second method simply uses the list separator special variable $, to put a space between each list element as it is printed.


    Dave

      Don't rely on that sort of thing (string interpolation, etc).
      Huh? Why is that? Does string interpolation only work half the time?

      I prefer "@array" over join " ", @array any day, and twice on Mondays. It's less messy:

      print "The first results are [@first]; the second are [@second]\n" +;
      vs.
      print "The first results are [", join (" ", @first), "; the second are [", join (" ", @second), "]\n";
      And pity you if you forget to leave off a set of parens.

      Abigail

        I understand what you're saying Abigail, and it makes absolute sense that if all you want is an array interpolated into a string with single spaces between elements, you'll use "@array". But he was trying to sort, and wanted the results to be output with single-spaces between each element. Fine, but he was going about it by inventing syntaxes that simply didn't do what he wanted. For one, putting "@array" in quotes as an argument to sort.

        And though interpolation has its place, you probably wouldn't recommend this (except for maybe in an obfu:

        print "@{[sort @array]}";

        Or maybe you would. There is always more than one way to do it. Though this method probably creates two copies of @array; one being an anonyomous array, and the second being the interpolated string.

        Anyway, thanks for pointing out the overstatement of my post. You are (as is often the case) correct.


        Dave

Re: array sorting
by sulfericacid (Deacon) on Jan 29, 2004 at 07:28 UTC
    You could do what the others are doing, but I personally don't understand either. I ran all your examples and now I'm wondering why when you treat a scalar as a list, it doesn't get sorted..but as a string, it does. Then the other people are joining on the scalar as if it were a string, I'm not sure I understand that either.

    How I do it is a little different:

    for (sort @animals) { print "$_ "; }
    UPDATE: Well what do you know, without realizing it I didn't interpolete(sp) @animals either.. But I still understand this better than joining a a blank line on a string (how does it know where the spaces are to be printed?)


    "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

    sulfericacid
      Take a deep breath and look at it again.

      @sorted = sort @unsorted; $string = join " ", @sorted; print $string;

      That's the same as....

      print join( " ", sort @unsorted );

      Except that you're not using two intermediate variables. sort takes a list or array as input, and spits out a sorted list which you can either slurp into an array, or send into the input side of join. join takes a list or array as input, and joins its elements together with whatever you put between the quotes, to create a single big-old string. print takes a list (even if the list is one element... and in this case the one element is the string which is the output of join).

      Hope this helps...


      Dave

Re: array sorting
by Roger (Parson) on Jan 29, 2004 at 07:01 UTC
    my @animals = ("frog", "toad", "snake", "grasshopper", "bird"); print join (' ', sort @animals), "\n"; # or print qq{@{[ sort @animals ]}}, "\n"; # etc...

      Tsk, tsk.

      Your code had only the reference to join when you posted, and after Caron showed the @{[ sort @animals ]} idiom, then you added that as well.

      Not good, Roger. At least, acknowledge that it was an update. Don't learn from somebody else's worst practices.

      The PM Observer

        Damn, I thought nobody saw that. ;-)

        You must have seen my initial post within the first minute I posted, 'cause I updated my post before davido made his first post.

        I hesitated to include the interpolated hash slice solution initially because I think of it as an obfuscated over-kill, but included in my update for completeness. I was going to add the print "$_ " for @animals solution too but stopped short because that solution will print an additional blank space after the last element in the array, which I consider as not a proper solution.

        So the answer is -
        yes, I admit I have updated without labelling it as an update.
        no, I didn't see Caron's post before my update.