array_sum on key

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

array_sum on key

Post 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'];
                }
 
 
User avatar
jackpf
DevNet Resident
Posts: 2119
Joined: Sun Feb 15, 2009 7:22 pm
Location: Ipswich, UK

Re: array_sum on key

Post 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?
Mark Baker
Forum Regular
Posts: 710
Joined: Thu Oct 30, 2008 6:24 pm

Re: array_sum on key

Post by Mark Baker »

What is the actual structure of your array?
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Re: array_sum on key

Post 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
        )
 
)
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Re: array_sum on key

Post 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.
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Re: array_sum on key

Post 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.
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Re: array_sum on key

Post 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.
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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;
        }
}
 
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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?
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: array_sum on key

Post 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);
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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?
Skip_B
Forum Newbie
Posts: 12
Joined: Mon Aug 17, 2009 9:20 am

Re: array_sum on key

Post 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. :?
Post Reply