I have a two dimensional array that I need to sort based on a total of values in the second dimension. The top level array has a part number and another array as its elements. The second array consists of defect types and defect quantity corresponding to the part number.
I am able to sort the second defect array by defect type (so whichever type has the highest quantity shows up first) but I am not sure how to sort so that the parts with the highest total defects are first. Essentially I need to sort based on the total quantities in the second array, but I am not sure how to do that on the fly. Here is a print_r of the array

Part#101 Array ( [Scratches] => 6 )
Part#102 Array ( [Scratches] => 174 [Handling] => 22 [Supplier Mold Defect] => 9 [Dirt] => 9 )
Part#103 Array ( [Scratches] => 167 [Dirt] => 116 [Handling] => 4 [Water Spots] => 3 [Supplier Mold Defect] => 1 )
Part#104 Array ( [Scratches] => 20 [Supplier Mold Defect] => 4 )

After sorting the part order should be:
Part#103 (291 total defects)
Part#102 (214 total defects)
Part#104 (24 total defects)
Part#101 (6 total defects)

    How are you creating the arrays? One option to consider would be to add one more dimension to the array with a sum of the total defects, then sort on that dimension...

      I'm creating the array by parsing a SQL query. The database contains one or more entries for each defect type depending on the date range selected. Once I pull the basic query I sort through it and create the new query to count up the defects for each. Below is the code that creates the query.

      $totals = array(); //create array to hold totals
      $deptScrap = 0; //total scrap for department
      //$partScrap = 0;	//total scrap for partnumber
      while ($row = mysql_fetch_array($dbResult, MYSQL_ASSOC)) {
      	if(!isset($totals[$row['Part']])) {	//search array to see if current part number is in it
      		$totals[$row['Part']] = array(); //create array to store part info
      	}
      	if(!isset($totals[$row['Part']][$row['Type']]))	{
      		$totals[$row['Part']][$row['Type']] = 0;	//create running total of defects per defect type and set to zero
      		$totals[$row['Part']][$row['Type']] += $row['Defects'];
      		$deptScrap += $row['Defects'];	//add to running total of total defects for department
      	} else {
      		$totals[$row['Part']][$row['Type']] += $row['Defects'];	//Add the number of defects per defect type to running total
      		$deptScrap += $row['Defects'];	//add to running total of total defects for department
      	}
      
      }
      

      So I could maybe push another element on the end of this array with the total defects as the value? As you can see I am already totaling the defects so thats already there. Then when I sorted the whole array I would sort on the last element in each of the second array? Guess I am not sure exactly how to implement this, if this is the right track if the first place.

      Or would I push the total defects onto the end of the first array as another element value and then sort on that? Would I do a uasort and pass to a function that takes 3 variables and then sort on $a & $c, the first and last elements in the array?

        Anybody have any ideas? I tried adding the defect count to the $totals array, but all I get is the last part numbers total.

        $totals["TotalPartScrap"]=$defectCount;

        I'm stuck.

          (untested)

          function mySort($a, $b)
          {
             $aTotal = array_sum($a);
             $bTotal = array_sum($b);
             return($aTotal - $bTotal);
          }
          usort($totals, 'mySort');
          

            QUOTE=NogDog

            function mySort($a, $b)
            {
               $aTotal = array_sum($a);
               $bTotal = array_sum($b);
               return($aTotal - $bTotal);
            }
            usort($totals, 'mySort');
            

            [/QUOTE]

            prolly want to return ! of that value since he wants highest first... or simply reverse the array when its done, but why do 2 steps when the sort can do it all?

            but your method should work just reverse order from whats expected

              tekky wrote:

              prolly want to return ! of that value since he wants highest first... or simply reverse the array when its done, but why do 2 steps when the sort can do it all?

              but your method should work just reverse order from whats expected

              Yes, if you want the highest first, reverse the order of the variables in the return statement of the sort function.

              I'm not sure what you mean regarding "why do 2 steps when the sort can do it all?" If you mean using an anonymous [man]create_function/man function for the 2nd arg of usort(), I figured that was another level of complication not needed at this point.

                NogDog wrote:

                Yes, if you want the highest first, reverse the order of the variables in the return statement of the sort function.

                I'm not sure what you mean regarding "why do 2 steps when the sort can do it all?" If you mean using an anonymous [man]create_function/man function for the 2nd arg of usort(), I figured that was another level of complication not needed at this point.

                That comment was in reference to running array_reverse after the sort (versus fixing the sort to return them in the right order)

                  Ahh...somehow that didn't register on my brain. I think it's time for me to take a nap. 🙂

                    Thanks! I was close with my own sort, but I was trying to do it from inside the foreach loop. Once I moved it before the foreach it stacked right up.

                    Here is the sort I was trying to use (and the one I used for the defect types themselves)

                    function sort_defects($a, $b) {
                    	if ($a > $b) return -1;
                    	if ($a < $b) return 1;
                    	return 0;
                    }
                    

                    Here is the final print_r with the part# totals tacked on the end.
                    Part# W10098960 Array ( [Scratches] => 167 [Dirt] => 116 [Handling] => 4 [Water Spots] => 3 [Supplier Mold Defect] => 1 ) Total Part Defects: 291
                    Part# W10098940 Array ( [Scratches] => 174 [Handling] => 22 [Supplier Mold Defect] => 9 [Dirt] => 9 ) Total Part Defects: 214
                    Part# W10100388 Array ( [Scratches] => 20 [Supplier Mold Defect] => 4 ) Total Part Defects: 24
                    Part# W10098830 Array ( [Scratches] => 6 ) Total Part Defects: 6

                      You over complicate your sort fuction though...

                      Think about it... we'll use 1 3 5 7 11 as our values....

                      if you simply return $b-a; you get
                      1-3 = -2 bring you to 3 1 5 7 11
                      3-5 = -2 means 5 3 1 7 11
                      5-7 = -2 means 7 5 3 1 7 11
                      7-11 = -4 means 11 7 5 3 1
                      (obviously I did this in the most optimal way to avoid redudant checks, results are still the same though)

                      but now you have a 1 line sort function 😉

                        Write a Reply...