Sorting arrays

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Paul Lautman

    Sorting arrays

    I'm having some trouble understanding what is happening with some array
    sorting functions. In all cases, my compare function is:
    function compare($x, $y)
    {
    if ( $x[1] == $y[1] )
    return 0;
    else if ( $x[1] < $y[1] )
    return -1;
    else
    return 1;
    }
    I started with this:
    $contents = array( array( 'TIR', 'Tires', 100 ),
    array( 'OIL', 'Oil', 10 ),
    array( 'SPK', 'Spark Plugs', 4 ) );
    echo '<br>XXX<br>';
    foreach($conten ts as $r) {
    var_export($r);
    echo '<br>';
    }
    echo '<br>YYY<br>';
    uasort($content s, 'compare');
    foreach($conten ts as $r) {
    var_export($r);
    echo '<br>';
    }
    And the output, whether I use usort or uasort is always:
    XXX
    array ( 0 => 'TIR', 1 => 'Tires', 2 => 100, )
    array ( 0 => 'OIL', 1 => 'Oil', 2 => 10, )
    array ( 0 => 'SPK', 1 => 'Spark Plugs', 2 => 4, )

    YYY
    array ( 0 => 'OIL', 1 => 'Oil', 2 => 10, )
    array ( 0 => 'SPK', 1 => 'Spark Plugs', 2 => 4, )
    array ( 0 => 'TIR', 1 => 'Tires', 2 => 100, )
    But if I use uksort I get:
    XXX
    array ( 0 => 'TIR', 1 => 'Tires', 2 => 100, )
    array ( 0 => 'OIL', 1 => 'Oil', 2 => 10, )
    array ( 0 => 'SPK', 1 => 'Spark Plugs', 2 => 4, )

    YYY
    array ( 0 => 'SPK', 1 => 'Spark Plugs', 2 => 4, )
    array ( 0 => 'OIL', 1 => 'Oil', 2 => 10, )
    array ( 0 => 'TIR', 1 => 'Tires', 2 => 100, )

    But I cannot see why I get this reversal of order???

    I then tried:
    $contents = array( array( c=>'TIR', d=>'Tires', p=>100 ),
    array( c=>'OIL', d=>'Oil', p=>10 ),
    array( c=>'SPK', d=>'Spark Plugs', p=>4 ) );

    echo '<br>XXX<br>';
    foreach($conten ts as $r) {
    var_export($r);
    echo '<br>';
    }
    echo '<br>YYY<br>';
    uksort($content s, 'compare');
    foreach($conten ts as $r) {
    var_export($r);
    echo '<br>';
    }

    And this time the output, whether I use usort, uasort or uksort is always:
    XXX
    array ( 'c' => 'TIR', 'd' => 'Tires', 'p' => 100, )
    array ( 'c' => 'OIL', 'd' => 'Oil', 'p' => 10, )
    array ( 'c' => 'SPK', 'd' => 'Spark Plugs', 'p' => 4, )

    YYY
    array ( 'c' => 'SPK', 'd' => 'Spark Plugs', 'p' => 4, )
    array ( 'c' => 'OIL', 'd' => 'Oil', 'p' => 10, )
    array ( 'c' => 'TIR', 'd' => 'Tires', 'p' => 100, )

    Finally I tried:
    $contents = array( array( c=>'TIR', d=>'Tires', p=>100 ),
    array( c=>'OIL', a=>'Oil', p=>10 ),
    array( c=>'SPK', z=>'Spark Plugs', p=>4 ) );

    echo '<br>XXX<br>';
    foreach($conten ts as $r) {
    var_export($r);
    echo '<br>';
    }
    echo '<br>YYY<br>';
    uksort($content s, 'compare');
    foreach($conten ts as $r) {
    var_export($r);
    echo '<br>';
    }
    And once again, the outputs with usort, uasort or uksort is always:
    XXX
    array ( 'c' => 'TIR', 'd' => 'Tires', 'p' => 100, )
    array ( 'c' => 'OIL', 'd' => 'Oil', 'p' => 10, )
    array ( 'c' => 'SPK', 'd' => 'Spark Plugs', 'p' => 4, )

    YYY
    array ( 'c' => 'SPK', 'd' => 'Spark Plugs', 'p' => 4, )
    array ( 'c' => 'OIL', 'd' => 'Oil', 'p' => 10, )
    array ( 'c' => 'TIR', 'd' => 'Tires', 'p' => 100, )

    Can someone explain why none of the cases will sort the associative array by
    the second "column" and how I can find examples that will sow the
    differences between the 3 sort functions???

    TIA
    Paul


  • Paul Lautman

    #2
    Re: Sorting arrays

    I understand a bit more about it now, having tried something else, but I
    still can't find a difference between usort and uasort and neither can I
    figure out how to use uksort?


    Comment

    • Janwillem Borleffs

      #3
      Re: Sorting arrays

      Paul Lautman wrote:[color=blue]
      > I understand a bit more about it now, having tried something else,
      > but I still can't find a difference between usort and uasort and
      > neither can I figure out how to use uksort?
      >[/color]

      What is going wrong in the code from your previous post is that you are
      using numeric indexes on associative arrays, contained in $x and $y, which
      are using keys instead.

      Compare the following implementation with the one from your previous post:

      function compare($a, $b) {
      list(,$var_a) = array_values($a );
      list(,$var_b) = array_values($b );
      if ($var_a == $var_b) return 0;
      return $var_a < $var_b ? -1 : 1;
      }

      As you will see, list extracts the value from the second index from the
      array returned by array_values when applied to $a and $b.

      The difference between usort and uasort, is that the latter preserves the
      index association, while the first doesn't. As an example, with usort, the
      result will always be:

      array( 0 => ..., 1 => ....);

      while with uasort, depending on the structure of the original array, the
      result can be:

      array( 1 => ..., 0 => ....);

      The uksort function uses the keys/indexes, while the uasort function uses
      the values for sorting. For the array structure you've posted, uksort
      appears to be useless.


      JW


      Comment

      • Mladen Gogala

        #4
        Re: Sorting arrays

        On Sat, 20 May 2006 23:46:54 +0100, Paul Lautman wrote:
        [color=blue]
        > function compare($x, $y)
        > {
        > if ( $x[1] == $y[1] )
        > return 0;
        > else if ( $x[1] < $y[1] )
        > return -1;
        > else
        > return 1;
        > }[/color]

        Try with this:

        function compare($x, $y)
        {
        GLOBAL $contents;
        if ($contents[$x] == $contents[$y])
        return(0);
        else
        return ($contents[$x]<$contents[$y]? -1:1);

        }

        --


        Comment

        • Paul Lautman

          #5
          Re: Sorting arrays

          Janwillem Borleffs wrote:[color=blue]
          > Paul Lautman wrote:[color=green]
          >> I understand a bit more about it now, having tried something else,
          >> but I still can't find a difference between usort and uasort and
          >> neither can I figure out how to use uksort?
          >>[/color]
          >
          > What is going wrong in the code from your previous post is that you
          > are using numeric indexes on associative arrays, contained in $x and
          > $y, which are using keys instead.
          >
          > Compare the following implementation with the one from your previous
          > post:
          > function compare($a, $b) {
          > list(,$var_a) = array_values($a );
          > list(,$var_b) = array_values($b );
          > if ($var_a == $var_b) return 0;
          > return $var_a < $var_b ? -1 : 1;
          > }
          >
          > As you will see, list extracts the value from the second index from
          > the array returned by array_values when applied to $a and $b.
          >
          > The difference between usort and uasort, is that the latter preserves
          > the index association, while the first doesn't. As an example, with
          > usort, the result will always be:
          >
          > array( 0 => ..., 1 => ....);
          >
          > while with uasort, depending on the structure of the original array,
          > the result can be:
          >
          > array( 1 => ..., 0 => ....);
          >
          > The uksort function uses the keys/indexes, while the uasort function
          > uses the values for sorting. For the array structure you've posted,
          > uksort appears to be useless.
          >
          >
          > JW[/color]
          Yeah I worked out the indexes problem.

          Can you give me an example of where usort and uasort give different outputs
          and how uksort would be used?



          Comment

          • Paul Lautman

            #6
            Re: Sorting arrays

            Mladen Gogala wrote:[color=blue]
            > On Sat, 20 May 2006 23:46:54 +0100, Paul Lautman wrote:
            >[color=green]
            >> function compare($x, $y)
            >> {
            >> if ( $x[1] == $y[1] )
            >> return 0;
            >> else if ( $x[1] < $y[1] )
            >> return -1;
            >> else
            >> return 1;
            >> }[/color]
            >
            > Try with this:
            >
            > function compare($x, $y)
            > {
            > GLOBAL $contents;
            > if ($contents[$x] == $contents[$y])
            > return(0);
            > else
            > return ($contents[$x]<$contents[$y]? -1:1);
            >
            > }[/color]

            What is this supposed to achieve?


            Comment

            • Janwillem Borleffs

              #7
              Re: Sorting arrays

              Paul Lautman wrote:[color=blue]
              > Can you give me an example of where usort and uasort give different
              > outputs and how uksort would be used?
              >[/color]

              function cmp($a, $b) {
              if ($a == $b) return 0;
              return $a < $b ? -1 : 1;
              }

              $array = array('b' => 200, 'a' => 50, 'A' => 100);
              $usort = $uasort = $uksort = $array;

              print 'original array:<br>';
              print_r($array) ;

              print '<hr>usort: sorted by value, keys are not preserved:<br>' ;
              usort($usort, 'cmp');
              print_r($usort) ;

              print '<hr>uasort: sorted by value, keys are preserved:<br>' ;
              uasort($uasort, 'cmp');
              print_r($uasort );

              print '<hr>uksort: sorted by key;<br>';
              print '"A" put before "a" because of its lower ASCII value:<br>';
              uksort($uksort, 'cmp');
              print_r($uksort );


              JW


              Comment

              • Paul Lautman

                #8
                Re: Sorting arrays

                Janwillem Borleffs wrote:[color=blue]
                > Paul Lautman wrote:[color=green]
                >> Can you give me an example of where usort and uasort give different
                >> outputs and how uksort would be used?
                >>[/color]
                >
                > function cmp($a, $b) {
                > if ($a == $b) return 0;
                > return $a < $b ? -1 : 1;
                > }
                >
                > $array = array('b' => 200, 'a' => 50, 'A' => 100);
                > $usort = $uasort = $uksort = $array;
                >
                > print 'original array:<br>';
                > print_r($array) ;
                >
                > print '<hr>usort: sorted by value, keys are not preserved:<br>' ;
                > usort($usort, 'cmp');
                > print_r($usort) ;
                >
                > print '<hr>uasort: sorted by value, keys are preserved:<br>' ;
                > uasort($uasort, 'cmp');
                > print_r($uasort );
                >
                > print '<hr>uksort: sorted by key;<br>';
                > print '"A" put before "a" because of its lower ASCII value:<br>';
                > uksort($uksort, 'cmp');
                > print_r($uksort );
                >
                >
                > JW[/color]

                Cheers for that, do you also know why I see the oder reversal (see the first
                post)?


                Comment

                • Janwillem Borleffs

                  #9
                  Re: Sorting arrays

                  Paul Lautman wrote:[color=blue]
                  > Cheers for that, do you also know why I see the oder reversal (see
                  > the first post)?
                  >[/color]

                  In your original compare function, the passed numeric indexes are converted
                  to strings (because of the var[1] syntax, which is a deprecated use of
                  var{1} with scalars) of which you are requesting the second character that
                  doesn't exist. In effect, you are comparing '' with '', which is equal.

                  If you look at the sequences passed, from the original array, index 1 is
                  compared to index 0 and index 2 is compared to index 1.

                  The result of the first comparison would be:

                  1 => array( 'OIL', 'Oil', 10 )
                  0 => array( 'TIR', 'Tires', 100 )

                  The result of the second comparison would be:

                  2 => array( 'SPK', 'Spark Plugs', 4 )
                  1 => array( 'OIL', 'Oil', 10 )
                  0 => array( 'TIR', 'Tires', 100 )

                  So, the reversal effect is the result of the first argument passed to the
                  compare function being considered to be equal to the second one and they are
                  therefore sorted in the order they where passed.


                  JW


                  Comment

                  • Janwillem Borleffs

                    #10
                    Re: Sorting arrays

                    Janwillem Borleffs wrote:[color=blue]
                    > In your original compare function, the passed numeric indexes are
                    > converted to strings (because of the var[1] syntax, which is a
                    > deprecated use of var{1} with scalars)[/color]

                    "which is a deprecated use of var{1} with scalars" should read:
                    "which is a deprecated use of var{1} on strings"

                    JW


                    Comment

                    • Paul Lautman

                      #11
                      Re: Sorting arrays

                      Janwillem Borleffs wrote:[color=blue]
                      > Paul Lautman wrote:[color=green]
                      >> Cheers for that, do you also know why I see the oder reversal (see
                      >> the first post)?
                      >>[/color]
                      >
                      > In your original compare function, the passed numeric indexes are
                      > converted to strings (because of the var[1] syntax, which is a
                      > deprecated use of var{1} with scalars) of which you are requesting
                      > the second character that doesn't exist. In effect, you are comparing
                      > '' with '', which is equal.
                      > If you look at the sequences passed, from the original array, index 1
                      > is compared to index 0 and index 2 is compared to index 1.
                      >
                      > The result of the first comparison would be:
                      >
                      > 1 => array( 'OIL', 'Oil', 10 )
                      > 0 => array( 'TIR', 'Tires', 100 )
                      >
                      > The result of the second comparison would be:
                      >
                      > 2 => array( 'SPK', 'Spark Plugs', 4 )
                      > 1 => array( 'OIL', 'Oil', 10 )
                      > 0 => array( 'TIR', 'Tires', 100 )
                      >
                      > So, the reversal effect is the result of the first argument passed to
                      > the compare function being considered to be equal to the second one
                      > and they are therefore sorted in the order they where passed.
                      >
                      >
                      > JW[/color]

                      Thank you for your very full and thorough explanation.


                      Comment

                      • Mladen Gogala

                        #12
                        Re: Sorting arrays

                        On Sun, 21 May 2006 13:02:53 +0100, Paul Lautman wrote:
                        [color=blue]
                        > What is this supposed to achieve?[/color]

                        Sort hash keys according to the hash values.

                        --


                        Comment

                        Working...