Page 1 of 2

array_sum on key

Posted: Mon Aug 17, 2009 9:31 am
by Skip_B
I need to total the values in an array only for a particular key. Points table key is points. I have researched this on the web and everything is either too basic or complex. I have settled on a couple of approaches which I have roughed in below. I think either can be made to work and I am leaning towards the array_sum. I know the following code is not functional. I am looking for advice on which approach to spend my day working on. The array_sum has the issue that any player who has no points returns a value of NULL which causes the array_sum function to fail. I can modify my query function to supply an empty array and that is what I am working on but I would value any advice. The second approach is commented out. It will be one or the other, not both. In the first case I am echoing as a test only. The value actually gets stored to a variable.

Code: Select all

 
                while($points = ($player_points))
                {
                array_sum ($player_points);
                echo $player_points; 
    
//              $total = 0;
//              foreach ($points as $type => $player_points) 
//              {
//              $total = $total + $points[$type]['points'];
                }
 
 

Re: array_sum on key

Posted: Mon Aug 17, 2009 9:48 am
by jackpf
I'm not entirely sure what you're trying to do...

Could you give some example as to what $player_points might be?

Re: array_sum on key

Posted: Mon Aug 17, 2009 10:18 am
by Mark Baker
What is the actual structure of your array?

Re: array_sum on key

Posted: Mon Aug 17, 2009 10:37 am
by Skip_B
I hope this isn't a duplicate post. I was working on a reply and got distracted. I can't find my draft or completed post so here goes again.
I have a table of taverns, players at those taverns and of points for each player. I need to total the points for each player then print out a list of all the players at one tavern with their point totals and arrange them by their total points.

I decided to find the tavern first. Accomplished.
Then find a list of the players of that tavern. Accomplished.
Then total the points for that player and store it to a variable. Stuck.
I am attempting to step through the list of players with a while statement,
adding up the point totals for a single player. Later I will need to output a list of players and their points, arranged by point totals.
The fields in the Points table are : id, player_id, tavern_id,date,tnumber,finished,points. 6 of the fields are integers but I only want to total the [points]. The sum_array function would probably look something like

Code: Select all

array_sum ($player_points[points])
.

The first obstacle I ran into with the sum_array approach was an error returned by my get_points_by_id function for the players who had no points. The RETURN value from the function is NULL for players with no points. The sum_array function is expecting an array and there is no array for players with no points. I am working on building an array with a points value of 0 and returning that instead of NULL. I THINK that will work but am not sure.

Another approach is to have an if(!NULL) condition to deal with the players with no points.

Re: array_sum on key

Posted: Mon Aug 17, 2009 11:24 am
by Ollie Saunders
You approach so far seems good.
Then total the points for that player and store it to a variable. Stuck.
I can't really tell you how to do this without some knowledge of the API you're working with. All I can do is to provide you with an example implementation for what you describe and a solution for that. He's one:

Code: Select all

$players = array(
    'Gary'    => array('tavern' => 'green', 'points' => array(1, 2, 2)), 
    'Richard' => array('tavern' => 'red',   'points' => array(6, 4)), 
    'Amanda'  => array('tavern' => 'green', 'points' => array(1, 5, 9)), 
    'Edith'   => array('tavern' => 'green', 'points' => array(6)));
 
function cmpPlayerTotalPoints($a, $b) { return $b['totalPoints'] - $a['totalPoints']; }
 
$greenTavernPlayers = array();
foreach ($players as $name => $player) {
    if ($player['tavern'] === 'green') {
        $player['totalPoints'] = array_sum($player['points']);
        $greenTavernPlayers[$name] = $player; } }
        
uasort($greenTavernPlayers, 'cmpPlayerTotalPoints');
print_r($greenTavernPlayers);
Producing:

Code: Select all

Array
(
    [Amanda] => Array
        (
            [tavern] => green
            [points] => Array
                (
                    [0] => 1
                    [1] => 5
                    [2] => 9
                )
 
            [totalPoints] => 15
        )
 
    [Edith] => Array
        (
            [tavern] => green
            [points] => Array
                (
                    [0] => 6
                )
 
            [totalPoints] => 6
        )
 
    [Gary] => Array
        (
            [tavern] => green
            [points] => Array
                (
                    [0] => 1
                    [1] => 2
                    [2] => 2
                )
 
            [totalPoints] => 5
        )
 
)

Re: array_sum on key

Posted: Mon Aug 17, 2009 11:32 am
by Ollie Saunders
The first obstacle I ran into with the sum_array approach was an error returned by my get_points_by_id function for the players who had no points. The RETURN value from the function is NULL for players with no points.
That's bad design. Avoid returning more than one type of value from a function unless necessary. Sometimes there are good reasons but generally not as often as people think. In cases where all you can provide is null instead of a useful value either throw an exception or allow a fallback value to be specified. When you have a function called get_points_by_id it should get points, null isn't a number of points but 0 is.

Consider

Code: Select all

$a = 1; $b = 2; $c = null; $d = 7;
$total = $a + $b + $c + $d; # Error
versus:

Code: Select all

$a = 1; $b = 2; $c = 0; $d = 7;
$total = $a + $b + $c + $d; # => 10
Another approach is to have an if(!NULL) condition to deal with the players with no points.
That works but it's an extra step that can be avoided and less code is better.

Re: array_sum on key

Posted: Mon Aug 17, 2009 12:04 pm
by Skip_B
Before I got your post I experimented with the if statement. Here is what I came up with.

Code: Select all

           get_points_by_id($player_id); [color=#FF8040]// The return value here is $player_points which is a resource[/color]
            $points = get_points_by_id($player_id);
            echo ($points); // I have ar array at this point
                if ($points)
                {
                    $rows = mysql_num_rows($player_points);  [color=#FF8040]// Error: Warning: mysql_num_rows() [/color]
                    [color=#FF8040]// expects parameter 1 to be resource, integer given in G:\wamp\www\tavernpokerleague.com\player_list.php [/color]
                    [color=#FF8040]//on line 51.  I don't know how I went from a resource to an integer at this point.  $player_id was a returned resource 6 lines up. [/color] 
                   [color=#FF8040] //Any thoughts?[/color]
                    $i=0;
                    while ($i < $rows) 
                    {
                        $points = array_sum ($player_points['points']);
                        echo $player_points; 
                        echo $points; 
                    }
                }   
                else 
                {
                    $player_points = 0;
                }
 

Should I scrap this approach and go back to passing the empty array for the players with no points?


If I am to go back to building the array for the 0 points earners, this is what I had:

Code: Select all

         "$player_points"  = array(
          "id" => "0", 
          "player_id" => "1",
          "date" => "01/01/2001",
          "tnumber" =>"1",
          "finished" =>"0",
           "points" >="0"); 
        return $player_points;
 
Either solutions seems to work but I still get the error mentioned above when I try to step through the rows and sum the points.

Re: array_sum on key

Posted: Mon Aug 17, 2009 12:31 pm
by Ollie Saunders

Code: Select all

get_points_by_id($player_id); // The return value here is $player_points which is a resource
No, the return value is being discarded. In the snippet you posted $player_points is never assigned to, so I don't know what value it contains.

Code: Select all

substr('foo', 2); # discarded return
$monkey = substr('foo', 2); # return value being assigned to $monkey
Should I scrap this approach and go back to passing the empty array for the players with no points?
Are you asking about what to return for get_points_by_id()? If you are, my prior recommendation stands; return 0 for no points.

Re: array_sum on key

Posted: Mon Aug 17, 2009 2:41 pm
by Skip_B
First, thanks for your time. I appreciate it.
First item: Originally I had

Code: Select all

$player_points = get_points_by_id($player_id);
Which converts the returned resource $player_points from a resource to an array. But when I got to

Code: Select all

$rows = mysql_num_rows($player_points);
I got the error that it expected the first parameter to be a resource, not an array. So I changed

Code: Select all

$player_points = get_points_by_id($player_id);
to

Code: Select all

$player = get_points_by_id($player_id);
in an attempt to leave $player_points as a resource.

That didn't work. As you say it was discarded. Whatever happened, it turned into an integer value instead of a resource. To use it in

Code: Select all

$rows = mysql_num_rows($player_points);
it seems to have to be a resource, not an array or an integer. It is returned from my function as a resource. How do I keep it long enough to use it in my if without converting it to an array?

Second item:
I literally tried

Code: Select all

return();
. That errored. I tried

Code: Select all

return $player_points ();
which also failed. Sorry to be so dense. What exactly did you have in mind. To be compatible with the sum_array function which is to come I need to return an empty array here, not just NULL or a False or even a 0 value. Anything other than an array and I have to do the if statement to exclude it from the sum_array function.

Re: array_sum on key

Posted: Mon Aug 17, 2009 3:29 pm
by Ollie Saunders
mysql_num_rows() takes a query result resource. A query result resource is returned from mysql_query(). So store the return value from mysql_query() and use that for mysql_num_rows().

Out of interest do you know how to declare a function and return a value? I'm worried you don't have a proper grasp of what functions are and how they work, which might be the reason for your difficulties.

Re: array_sum on key

Posted: Mon Aug 17, 2009 4:38 pm
by Skip_B
I wouldn't put anything past me. :) but I use a lot of functions and return values from them. This function works fine and returns found values with no sweat. But if there is no find I was returning NULL. That is not acceptable to sum_array which requires a valid array.

I could not get your return for a no find to work. That I clearly don't understand or you aren't understanding the need for the empty array. I am creating a zero points value array and returning that and it is working. But if you have a simpler way I am all ears. Here is the function:

Code: Select all

    function get_points_by_id($player_id) 
{
        global $connection;
        $query = "SELECT * ";
        $query .= "FROM points ";
        $query .= "WHERE player_id=" . $player_id ." ";
        $result_set = mysql_query($query, $connection);
        confirm_query($result_set);
        [color=#FF8080]// REMEMBER:[/color]
       [color=#FF8080] // if no rows are returned, fetch_array will return false (original reminder to myself and this is the issue.)[/color]
        if ($player_points = mysql_fetch_array($result_set)) 
        {
            return $player_points;
        } else 
        {  [color=#FF8080]//  This is the array I created to build a 0 point array and return it.  Not elegant but it works.[/color]
          $player_points  = array(
          'id' => '0', 
          'player_id' => '1',
          'date' => '01/01/2001',
          'tnumber' =>'1',
          'finished' =>'1',
           'points' >='0'
           ); 
            return $player_points;
        }
}
 

Re: array_sum on key

Posted: Mon Aug 17, 2009 4:50 pm
by Skip_B
"mysql_num_rows() takes a query result resource. A query result resource is returned from mysql_query()." This I understand. So store the return value from mysql_query() and use that for mysql_num_rows(). This is the missing piece for me. I don't know how to "store" a resource and then reuse it. I have always simply converted it to an array and then used the array. Here I need to perform a mysql_num_rows for my while loop but not until I have added an if condition. By the time I try to use it, it has been discarded. How do I "store" it? then reuse it?

Re: array_sum on key

Posted: Mon Aug 17, 2009 4:53 pm
by John Cartwright
You would store the resource by simpler assigning the return value of mysql_query().

I.e.,

Code: Select all

$result = mysql_query($sql) or die(mysql_error()); //$result is now a resource
then when you need to know the # of rows, simply pass $result to mysql_num_rows(),

I.e.,

Code: Select all

$numrows = mysql_num_rows($result);

Re: array_sum on key

Posted: Mon Aug 17, 2009 5:23 pm
by Skip_B
Ok, looking at my function:

Code: Select all

    function get_points_by_id($player_id) 
{
        global $connection;
        $query = "SELECT * ";
        $query .= "FROM points ";
        $query .= "WHERE player_id=" . $player_id ." ";
        $result_set = mysql_query($query, $connection);
        confirm_query($result_set);  The confirm_query is just a function that equals or die
 
is the equivalent of

Code: Select all

  1. $result = mysql_query($sql) or die(mysql_error()); //$result is now a resource
But then I need to get a subset set for the individual so I do

Code: Select all

if ($player_points = mysql_fetch_array($result_set)) 
        {
            return $player_points;
 
$player_points is a resource and is what I return. In your example this should be the equivalent of your result, right? After I return that value I capture it with

Code: Select all

        $player_points = get_points_by_id($player_id);
 
which converts it to an array. But if I don't do this it discards my returned $player_points Resource. If I weren't using a function I think it would be more straight forward. Don't I have to capture my returned value? and if so, how do I do that so it doesn't change it to an array?

Re: array_sum on key

Posted: Mon Aug 17, 2009 5:32 pm
by Skip_B
I tried simply commenting out the

Code: Select all

//      $player_points = get_points_by_id($player_id);
 
which captures my return value and it seems to work. It is hard to tell because I error out a couple of lines later but is that all I had to do was not capture the return resource?

I have never worked with a resource returned from a function without immediately converting it to an array. :?