Jump to content

[SOLVED] Question about sorting multidimensional arrays


isbhenrylu

Recommended Posts

Hi guys,

I can sort arrays already using the sort, ksort, or asort functions. But for multidimensional arrays, I can't do it. I looked up the php book by Luke Welling and Laura Thomson and here's their array :

 

$products = array (array( 'TIR', 'Tires', 100),
                          array( 'OIL', 'Oil', 10),
                          array( 'SPK', 'Spark Plugs', 4) );

 

According to them, to sort this array into alphabetical order using the second column in the array (which consists of Tires, Oil, and Spark Plugs), you need a self defined function and usort.

 

They say the code to sort it should contain these snippetes:

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

usort ($products, 'compare');

 

Problem is I still don't understand how to sort multidimensional arrays after looking at the example. Can someone please explain to me what their example is trying to do and how should the whole code to sort it look like?

 

If their example seems confusing to you as well, you could ignore it and tell me how you would do to sort multidimensional arrays

 

Thank you

 

Henry

 

Link to comment
Share on other sites

thx play_ for the link. Took a look at it but still have no idea what is the process that resulted in the multidimensional array being sorted.

 

I think my biggest problem is I don't understand what

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

 

is trying to do. How do how those values returned (0, 1, -1) contribute to the multidimensional array being solved?

 

Thanks

Link to comment
Share on other sites

If you look at the comparisons and the return values, it should be self explanatory.

 

If the comparison is equal then it returns a 0 - i.e. the values will not be sorted. If a 1 or -1 are returned then the values will be sorted: 1 will sort the first before the second and -1 will do the opposite. Which you return will depend on what direction you want the values sorted.

 

You can also use the function to sort on multiple columns. Let's say you have a multidimensional array in this format:

[0] => (
[firstname] => 'John',
[lastname] => 'Smith'.
[age] => 25
)

 

Now if you want to sort by age descending, last name ascending, then by first name ascending your function would look like this:

 

sortByAgeName($a, $b)
{
    if ($a['age'] != $b['age'])
    {
        return ($a[age] > $b[age]) ? 1 : -1;
    }
    else if ($a['lastname'] != $b['lastname'])
    {
        return ($a['lastname'] < $b['lastname']) ? 1 : -1;
    }
    else if($a['firstname'] != $b['firstname'])
    {
        return ($a['lastname'] < $b['lastname']) ? 1 : -1;
    }
    return 0;
}

Link to comment
Share on other sites

Really sorry guys but I'm quite new to PHP programming and what you said is getting me a bit confused.

 

For the post by mjdamato, I don't get the array you just posted. Why does your array start with this?

[0]=>

I thought multidimensional arrays look something like this?

$somevariable = array (array(), array(), array());

 

 

And also what does these mean?

? 1 : -1;

? 1 : -1;

? 1 : -1;

 

I think it's better if someone could explain how to sort multidimensional arrays using the function I posted in the first post because I'm more familiar with it.

Here's what I DO get:

1. The array is:

$products = array (array( 'TIR', 'Tires', 100),
                          array( 'OIL', 'Oil', 10),
                          array( 'SPK', 'Spark Plugs', 4) );

 

2. That compare() is a self defined function with 2 variables and that usort is just a function that tells $products to be sorted by compare().

 

Here's what I don't get:

1. what do the two variables in compare() $x and $y stand for as they have no correlation to the array I'm trying to solve. I guess it's just a format, so what should be the values that I substitute into them?

 

2. What happens when it returns 0 or 1 or -1? I can't see how the returning of either of those 3 values would result in the array being sorted by the 2nd column (Tires, Oil, Spark Plugs). How are these values then passed on in the process to contribute to the array being sorted?

 

3. What would the whole sorting function look like in the end? Exactly like this one, or is there anything else that I add to it for it to be sorted? (don't need the outputting bit because I know how to do that)

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

usort ($products, 'compare');

 

Thanks a lot for the help

Link to comment
Share on other sites

It's ok. Ask away :) we're here to help

 

 

I can't answer how that function works because i can't understand it myself. I understand what mjdamato said but i don't see where the actual sorting is taking place.

 

--------------------------------------------------------------------

For the post by mjdamato, I don't get the array you just posted. Why does your array start with this?

[0]=>

 

I thought multidimensional arrays look something like this?

$somevariable = array (array(), array(), array());

----------------------------------------------------------------------

 

Yes that is how multidimensional arrays look.

He just copied and pasted from an output.

 

If you do:

echo '<pre>';
print_r($products);
echo '</pre>';

 

you'll get the array's output in a neat manner..:

Array
(
    [0] => Array
        (
            [0] => TIR
            [1] => Tires
            [2] => 100
        )

    [1] => Array
        (
            [0] => OIL
            [1] => Oil
            [2] => 10
        )

    [2] => Array
        (
            [0] => SPK
            [1] => Spark Plugs
            [2] => 4
        )

)

 

Nothing to worry about.

 

 

 

About the

? 1 : -1;

 

That's called a ternary operator. It's a shortcut for IF statements.

 

(expression) ? true : false;

 

so if expression returns true, whatever is right after the ?, will execute, if not, then what's after the : will execute


$sex = 'm';
$gender = ( $sex == 'm' ) ? 'I am a male' : 'I am female'; // because $sex is 'm', $gender will hold the value "i am a male"

// another example
$age = 25;
echo ( $age == 25 ) ? 'you are 25' : 'you are not 25';

// the above is the same as
if( $age == 25 ) {
    echo 'you are 25';
} else {
    echo 'you are not 25';
}

 

Hope that's clear. if not let me know.

 

I'll let someone explain that function again :) I also still don't get it.

Link to comment
Share on other sites

Hi

 

Further to the above answers.

 

1. what do the two variables in compare() $x and $y stand for as they have no correlation to the array I'm trying to solve. I guess it's just a format, so what should be the values that I substitute into them?

 

Not quite. With a function you can pass variables. Within the function you refer to those variables by what they are declared as in the function statement.

 

For example:-

 

$SomeVariable = SomeFunction($Variable1, $Variable2);

 

function SomeFunction($A,$B)

{

}

 

Within the function SomeFunction, $A and $B contain the values of $Variable1 and $Variable2. By default they do not point to the same bit of storage, they just start with the same value (so if you change the value of $A it doesn't affect the value of $Variable1). This is called passing by value (you can optionally pass by reference if you want).

 

In the sort statement you are passing an array to usort and a function that is used to compare the values of the array. Each time the sort compares 2 sub arrays it will pass those 2 sub arrays to the function, and depending on whether the function returns -1, 0 or +1 it will know which of the 2 is to be treated as larger, or whether they are the same.

 

With a multidimensional array sort you could be sorting on any one of the members of the inner arraya, hence in the example it is sorting on member 1 of the arrays (ie  'Oil', 'Tires', 'Spark Plugs'); You could specify any member of the sub array to be the one to sort on (remember in php that array index 0 points to the first item in an array)

 

2. What happens when it returns 0 or 1 or -1? I can't see how the returning of either of those 3 values would result in the array being sorted by the 2nd column (Tires, Oil, Spark Plugs). How are these values then passed on in the process to contribute to the array being sorted?

 

The -1, 0 or +1 is just passed back to usort so the sort knows which is to be treated as larger / smaller and so sorted.

 

Ie. in the example usort passes array( 'TIR', 'Tires', 100) to the function as $x and array( 'OIL', 'Oil', 10) as $y. The function compares item [1] of each of those arrays to see which is larger. As 'Tires' is larger than 'Oil' it returns 1, and usort can decide to swap the 2 sub arrays around due to that.

 

The example is pretty simple, but the function could be very complex. For example you could do a call to a database for each of the parameters and decide which is larger based on the data returned from the database (please don't though, it would be hideously inefficient).

 

3. What would the whole sorting function look like in the end? Exactly like this one, or is there anything else that I add to it for it to be sorted? (don't need the outputting bit because I know how to do that)

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

usort ($products, 'compare');

 

Yep, that is pretty much it for a basic sort of a multi dimensional array on item [1] of the sub arrays.

 

All the best

 

Keith

Link to comment
Share on other sites

(Didn't see KickStart's post when posting this. Will take a look at his post right now)

 

thanks a lot play_ . Help greatly appreciated. Here's the bit in the php book that tries to explain the situation (though I have no clue what he's talking about) that might help.

 

Source: "PHP and MySQL Web Development" by Luke Welling and Laura Thomson

The array stores Bob's products with a code, a description, a price for each.

 

$products = array (array( 'TIR', 'Tires', 100),
                          array( 'OIL', 'Oil', 10),
                          array( 'SPK', 'Spark Plugs', 4) );

 

The following code sorts this array into alphabetical order using the second column in the array--the description:

 

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

usort ($products, 'compare');

 

The purpose of this function is to take two values and determine their order.

 

For this example, $x and $y parameters are two of the arrays within the main array, each representing one product. To acess the Description of the array $x, you type $x[1] because the Descrition is the second element in these arrays, and numbering starts at zero. You use $x[1] and $y[1] to compare each Description from the arrays passed into the function.

 

When a function ends, it can give a reply to the code that called it. The process is called returning a value. For example, the line return 1; sends the value 1 back to the coed that called the function.

 

To be used by usort(), the compare() function must compare $x and $y. The function must return - if $x equals $y, a negative number if it's less, or a positive number if it's greater. The function returns 0, 1, -1 depending on values of $x and $y.

 

The final line of code calls built-in function usort() with the array you want sorted and the name of the comaprison function.

 

Note: Should you run these snippets to test them, there will be no output. These snippets are meant to be part of large pieces of code you might write.

 

Hope this helps a little.

thanks.

 

Henry

Link to comment
Share on other sites

So kickstart,

 

If i understood what you said, that function doesn't sort the elements inside the subarrays, it sorts the subarrays themselves against each other?

 

if so, that would explain why i couldnt find the actual element sorting itself!

 

 

but thinking again, i can't be understanding this right.

 

If the function is comparing item[1] of each array and sorting based on item[1], if $arrayX[1] is 4 and $arrayY[1] is 2... it would place arrayY before arrayX...

but what if arrayX[0] was 0 and arrayY[0] was 1?

Link to comment
Share on other sites

Hi

 

It compares one sub array against another once.

 

In your example of  if $arrayX[1] is 4 and $arrayY[1] is 2... it would place arrayY before arrayX...  but what if arrayX[0] was 0 and arrayY[0] was 1?, it will sort arrayY before arrayX. In the function you have't cared about [0], and if you want to take account of that you would specify it.

 

For example if you want to sort on [0] the compare function might be:-

 

function (compare ($x, $y){

    if ($x[0] == $y[0]) {

        return 0;

    } else if ($x[0] < $y[0]) {

        return -1;

    } else {

        return 1;

    }

}

 

Further you might want to sort on another field if the first is equals.

 

For example, say you had an array of people and their ages:-

 

$products = array (array( 'Joe', 'Bloggs', 15),

                          array( 'Fred', 'Bloggs', 20),

                          array( 'Fred', 'Bloggs', 50),

                          array( 'Geoff', 'Smith', 4) );

 

Say you wanted this sorted into surname order, and within that into first name order:-

 

function (compare ($x, $y)

{

if ($x[1] == $y[1])

{

if ($x[0] == $y[0])

{

return 0;

}

else if ($x[0] < $y[0])

{

return -1;

}

else

{

return 1;

}

}

else if ($x[1] < $y[1])

{

return -1;

}

else

{

return 1;

}

}

 

You could carry on to deeper levels of comparison (eg, in that example say you wanted to sort by age if the first and surnames were the same).

 

The function is called numerous times. It just compares 2 elements. If php does a bubble sort then it would compare the first and second arrays using it, possibly swap them round, then the 2nd and 3rd arrays and again possibly swap them around, then the 3rd and 4th, etc, and after one pass the largest would be the last element, but all the others would be in a fairly random order. It would then go through again comparing the elements in the same away (but not bother with the last as it knows that is the largest one). And then again, ignoring the last 2. So on an array of 5 arrays it would call the function 10 seperate times.

 

All the best

 

Keith

Link to comment
Share on other sites

Doesn't the function from the book just provide logic to tell you how value A and value B relate to each other in an ordering sequence? The actual sorting would have to be handled in your own code, but you use the returned values from the compare() function to determine what to do with each set of values?

 

I've done this (sort multi-dimensional array) before but don't remember what section of my code it is in.

 

Oh I never noticed the usort() call either, don't remember playing around with that when I did my mutli array sorting code.

Link to comment
Share on other sites

Hi

 

It compares one sub array against another once.

 

In your example of  if $arrayX[1] is 4 and $arrayY[1] is 2... it would place arrayY before arrayX...  but what if arrayX[0] was 0 and arrayY[0] was 1?, it will sort arrayY before arrayX. In the function you have't cared about

, and if you want to take account of that you would specify it.

 

For example if you want to sort on [2]

the compare function might be:-

 

function (compare ($x, $y){

    if ($x[2] == $y[2]

) {

        return 0;

    } else if ($x[2] < $y[2]) {

        return -1;

    } else {

        return 1;

    }

}

 

Further you might want to sort on another field if the first is equals.

 

For example, say you had an array of people and their ages:-

 

$products = array (array('Cousin', 'Joe', 'Bloggs', 15),

                          array('Brother', Fred', 'Bloggs', 20),

                          array('Father', 'Fred', 'Bloggs', 50),

                          array('Neighbour', 'Geoff', 'Smith', 4) );

 

Say you wanted this sorted into surname order, and within that into first name order:-

 

function (compare ($x, $y)

{

  if ($x[2] == $y[2])

  {

      if ($x[1] == $y[1])

      {

        return 0;

      }

      else if ($x[1] < $y[1])

      {

        return -1;

      }

      else

      {

        return 1;

      }

  }

  else if ($x[2] < $y[2])

  {

      return -1;

  }

  else

  {

      return 1;

  }

}

 

You could carry on to deeper levels of comparison (eg, in that example say you wanted to sort by age if the first and surnames were the same).

 

The function is called numerous times. It just compares 2 elements. If php does a bubble sort then it would compare the first and second arrays using it, possibly swap them round, then the 2nd and 3rd arrays and again possibly swap them around, then the 3rd and 4th, etc, and after one pass the largest would be the last element, but all the others would be in a fairly random order. It would then go through again comparing the elements in the same away (but not bother with the last as it knows that is the largest one). And then again, ignoring the last 2. So on an array of 5 arrays it would call the function 10 seperate times.

 

All the best

 

Keith

 

PS - reposted as I seem to have managed to break the bbcode on this board with the previous post!

Link to comment
Share on other sites

Great help! I'm almost there. Let me see if I could get it right soon. Sorry for all the fuss guys.

 

$products = array (array( 'TIR', 'Tires', 100),
                          array( 'OIL', 'Oil', 10),
                          array( 'SPK', 'Spark Plugs', 4) );

 

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

usort ($products, 'compare');

 

Keith can you see if what I'm saying about the process is correct? Greatly appreciated

 

1. usort() function passes the 1st and 2nd subarrays of $products to compare(), which is array( 'TIR', 'Tires', 100) and array( 'OIL', 'Oil', 10).

 

2. Because Tires > Oil, the value "1" is returned. And usort recognizes that and switches array( 'TIR', 'Tires', 100) with array( 'OIL', 'Oil', 10), so currently the array is

$products = array (array( 'OIL', 'Oil', 10),
                          array( 'TIR', 'Tires', 100),
                          array( 'SPK', 'Spark Plugs', 4) );

 

3. Then usort() passes the current 2nd and 3rd subarrays to compare(), which are array( 'TIR', 'Tires', 100) and array( 'SPK', 'Spark Plugs', 4).

 

4. Because Tires > Spark Plugs, the value "1" is returned. And usort recognizes that and switches array( 'TIR', 'Tires', 100) with array( 'SPK', 'Spark Plugs', 4), so finally the array is sorted as:

$products = array (array( 'OIL', 'Oil', 10),
                          array( 'SPK', 'Spark Plugs', 4),
                          array( 'TIR', 'Tires', 100) );

 

And also another question. According to what you have said in your posts, when compare() returns "1" to usort(), usort() will recognize that and switch the two subarrays. So does that mean when "0" is returned the two subarrays don't change positions?

 

If so, what about if "-1" is returned? How does usort() deal with that? Does it leave the two subarrays unchanged as well? If so, why do you need one if() to return 0 and another else if() to return -1 if both of them are going to yield the same result: Which is keep the positions of the two subarrays under comparison unchanged. Then shouldn't it already be adequate to sort the array if the compare() function only returns two values? (either 0 or 1, or -1 or 1)

 

Thanx

Henry

Link to comment
Share on other sites

Yes on the points when they are equal or -1 is returned.

 

?? Don't quite get this sentence. Think part of it is missing?

 

So you mean that when -1 or 0 is returned, the location of the two subarrays don't switch? And only when 1 is returned that the two are switched around?

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.