Calculate overall and division ranking via arrays - php

This is a follow-up to Detect future duplicate values while iterating through MySQL results in PHP.
I have an SQL query which produces the results:
team_id division_id wins
-------------------------------
10 2 44
9 2 42
5 1 42
2 1 42
3 1 41
11 2 40
1 1 36
8 2 31
7 2 29
12 2 24
4 1 20
6 1 18
I'm trying to calculate a given team's overall and divisional rankings.
For example, team_id = 1:
Overall: 7
Divisional: 4
For team_id = 3:
Overall: 5
Divisional: 3
For team_id = 9:
Overall: T-2 //must indicate tie
Divisional: 2
As you can see from the linked previous question/answer, I can calculate the Overall rank just fine. The issue comes with calculating the divisional rank as well (including properly handling ties).
I've tried storing the results in a multi-dimensional array like $arr['wins']['division_id']['team_id'], such as...
44 => 2 => 10
42 => 1 => 5
2
2 => 9
41 => 1 => 3
40 => 11 => 2
...
But am stuck as to how to iterate through and get my two respective ranks, as well as detecting ties appropriately for each.

Try something like this:
// Dataset as defined on question
$arr = array(
array('team_id' => 10, 'division_id' => 2, 'wins' => 44),
array('team_id' => 9, 'division_id' => 2, 'wins' => 42),
array('team_id' => 5, 'division_id' => 1, 'wins' => 42),
array('team_id' => 2, 'division_id' => 1, 'wins' => 42),
array('team_id' => 3, 'division_id' => 1, 'wins' => 41),
array('team_id' => 11, 'division_id' => 2, 'wins' => 40),
array('team_id' => 1, 'division_id' => 1, 'wins' => 36),
array('team_id' => 8, 'division_id' => 2, 'wins' => 31),
array('team_id' => 7, 'division_id' => 2, 'wins' => 29),
array('team_id' => 12, 'division_id' => 2, 'wins' => 24),
array('team_id' => 4, 'division_id' => 1, 'wins' => 20),
array('team_id' => 6, 'division_id' => 1, 'wins' => 18));
$divisionTeam = array();
$divisionWins = array();
foreach($arr as $team) {
$divisionTeam[$team['division_id']][] = $team['team_id'];
$divisionWins[$team['division_id']][] = $team['wins'];
}
echo "<pre>";
foreach (array_keys($divisionTeam) as $division_id) {
$rank = 0;
$prevWins = -1;
echo "DIVISION $division_id \n";
foreach ($divisionTeam[$division_id] as $index => $team_id) {
if ($prevWins == $divisionWins[$division_id][$index]) {
echo $team_id . " T - " . $rank . "\n";
}
else {
$rank++;
echo $team_id . " " . $rank . "\n";
}
$prevWins = $divisionWins[$division_id][$index];
}
}
echo "</pre>";

Related

How to Create complex Array Structure in PHP

I have to make this kind of structure in array;
We have three ( 3 ) variables which creates this structure:
$numberOfParticipants = 38; // 38 is example
$numberOfParticipantsPerHeat = 8 // 8 is example
$numberOfHeats = 5; // 5 is example
Based on this variables I have this table:
The problem is that, I can't place the ' - ' or null after 31 OR 38. The task is that i have to make the arrays of array "almost equal" like the photo and must depend on the variables above. By the way, after I create the correct list I will slice the array to 5 or 6 or whatever parts I need this is not the problem, the problem is that I have to parse the list like this first. This is what I tried so far:
$calc1 = (int)round($numberOfParticipants * $numberOfParticipantsPerHeat, -1); //First round the numberOfParticipants to closest integer by 10
$readyArr = [];
for ($i = 1; $i <= $calc1; $i++) {
if ($i <= $numberOfParticipants) {
$readyArr[$i] = $i;
} else {
$readyArr[$i] = null;
}
}
The problem with this snippet is that it places the null at the end of the list not after 31, or based on the var.
This is the result I have:
array:40 [▼
1 => 1
2 => 2
3 => 3
4 => 4
5 => 5
6 => 6
7 => 7
8 => 8
9 => 9
10 => 10
11 => 11
12 => 12
13 => 13
14 => 14
15 => 15
16 => 16
17 => 17
18 => 18
19 => 19
20 => 20
21 => 21
22 => 22
23 => 23
24 => 24
25 => 25
26 => 26
27 => 27
28 => 28
29 => 29
30 => 30
31 => 31
32 => 32
33 => 33
34 => 34
35 => 35
36 => 36
37 => 37
38 => 38
39 => null
40 => null
]
The Array after partition I want should be:
array(
0 => array(0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6, 6 => 7, 7 => 8,),
1 => array(0 => 9, 1 => 10, 2 => 11, 3 => 12, 4 => 13, 5 => 14, 6 => 15, 7 => 16,),
2 => array(0 => 17, 1 => 18, 2 => 19, 3 => 20, 4 => 21, 5 => 22, 6 => 23, 7 => 24,),
3 => array(0 => 25, 1 => 26, 2 => 27, 3 => 28, 4 => 29, 5 => 30, 6 => 31, 7 => null,),
4 => array(0 => 32, 1 => 33, 2 => 34, 3 => 35, 4 => 36, 5 => 37, 6 => 38, 7 => null,),
);
Every help, every clue will be highly appreciated.
There are two things you need to know about the target structure:
How many players are in the first (which will always be the largest, if only by one) set.
$playersPerHeat = ceil($numberOfParticipants / $numberOfHeats);
// note this replaces your hard-coded $numberOfParticipantsPerHeat
You also need to know how many heats actually have that many, that is how many heats are actually full.
$fullHeats = $numberOfParticipants % $numberOfHeats ?: $numberOfHeats;
// The ?: bit means that if we get zero (ie. all equal heats), then we
// count all the heats instead, since they're all full.
Now it's easy!
$players = range(1,$numberOfParticipants);
$heats = array_merge(
array_chunk(
array_slice($players, 0, $fullHeats * $playersPerHeat),
$playersPerHeat
),
array_chunk(
array_slice($players, $fullHeats * $playersPerHeat),
$playersPerHeat - 1
)
);
That's it! Demo

How to group of 2 arrays

I have 2 arrays like this
$head = array(7, 1, 1, 1, 1, 14, 14, 14, 9, 9, 9, 13, 13, 13, 3, 3, 5, 8, 8, 8, 2, 2); //count =22
$customer = array(1, 7, 9, 13, 14, 1, 9, 13, 1, 13, 14, 1, 9, 14, 2, 8, 8, 2, 3, 5, 3, 8); //count=22
And I want to group this 2 arrays by consider at $customer, if $customer[0]=1 in $customer[1-21] and $head[1-21] will not have a value 1, such as in the $head[1] have a value 1, So delete at $head[1] and $customer[1]. And then consider at $customer[6]. The value is 9. It means in $head[7-21] and $customer[7-21] will not have a value 9.
I am trying to write a code for this concept like this. Here is my code
for ($i = 0; $i < count($head); $i++) {
for ($j = $i + 1; $j < count($customer); $j++) {
if ($customer[$i] == $head[$j]) {
unset($head[$j]);
unset($customer[$j]);
}
if ($customer[$i] == $customer[$j]) {
unset($head[$j]);
unset($customer[$j]);
}
}
}
print_r($head);
print_r($customer);
the result is of $head and $customer is:
Array ( [0] => 7 [6] => 14 [7] => 14 [13] => 13 [14] => 3 [15] => 3 [16] => 5 [17] => 8 [18] => 8 [19] => 8 [20] => 2 [21] => 2 )
Array ( [0] => 1 [6] => 9 [7] => 13 [13] => 14 [14] => 2 [15] => 8 [16] => 8 [17] => 2 [18] => 3 [19] => 5 [20] => 3 [21] => 8 )
I found that it's wrong. Because the real result should be:
Array ( [0] => 7 [6] => 14 [7] => 14 [14] => 3 [15] => 3 )
Array ( [0] => 1 [6] => 9 [7] => 13 [14] => 2 [15] => 8 )
Please help me to fix this problem.
Your logic is all ok but when you unset a particular index then all other index after when you iterate it again then i index is missing. Just open the error and warning then you will see
Notice: Undefined offset
I have just replaced your uset to assign it to ''. So you can understand it
<?php
$head = array(7, 1, 1, 1, 1, 14, 14, 14, 9, 9, 9, 13, 13, 13, 3, 3, 5, 8, 8, 8, 2, 2); //count =22
$customer = array(1, 7, 9, 13, 14, 1, 9, 13, 1, 13, 14, 1, 9, 14, 2, 8, 8, 2, 3, 5, 3, 8); //count=22
for ($i = 0; $i < count($head); $i++) {
for ($j = $i + 1; $j < count($customer); $j++) {
if ($customer[$i] == $head[$j]) {
$head[$j] = '';
$customer[$j] = '';
}
if ($customer[$i] == $customer[$j]) {
$head[$j] = '';
$customer[$j] = '';
}
}
}
print_r(array_diff($head, [''])); // remove all the '' entries
print_r(array_diff($customer, [''])); // remove all the '' entries
The problem is that count() only returns a count of the set elements in the array. So if you unset them it will be reduced and you won't arrive at the end of the array. To fix, calculate the count at the start and store in a variable:
$headcount = count($head);
$customercount = count($customer);
for ($i = 0; $i < $headcount; $i++) {
for ($j = $i + 1; $j < $customercount; $j++) {
if ($customer[$i] == $head[$j]) {
unset($head[$j]);
unset($customer[$j]);
}
if ($customer[$i] == $customer[$j]) {
unset($head[$j]);
unset($customer[$j]);
}
}
}

How to get array value then implode them into new array in PHP

I have an array:
Array
(
[10 - 20] => 3
[20 - 30] => 43
[30 - 40] => 5
[40 - 50] => 1
[50 - 60] => 0
[60 - 70] => 0
)
I want to make new array that will send via json. Now I have result in json like this(thanks for guys below who answered my question):
{"success":true,"data":["3","43","5","1","0","0"]}
I need json to be {"success":true,"data":[3,43,5,1,0,0]}, cause only with that format data show in line chart of highchart
Sorry for my stupid questionThank You
Update
Here's how you can get your response...
$values = array
(
'10 - 20' => 3,
'20 - 30' => 43,
'30 - 40' => 5,
'40 - 50' => 1,
'50 - 60' => 0,
'60 - 70' => 0,
);
$data = array_values($values);
$response = array('sucess' => true, 'data' => $data);
echo json_encode($response);
Use array_values, this can be done like so:
$values = array
(
'10 - 20' => 3,
'20 - 30' => 43,
'30 - 40' => 5,
'40 - 50' => 1,
'50 - 60' => 0,
'60 - 70' => 0,
);
$values = array_values($values);
$data = json_encode($values);
echo data;
Output:
[3,43,5,1,0,0]
You might be new to php, Declaration of associative array should be like below
$arr=array(
'[10 - 20]' => 3,
'[20 - 30]' => 43,
'[30 - 40]' => 5,
'[40 - 50]' => 1,
'[50 - 60]' => 0,
'[60 - 70]' => 0
);
array('Key'=>value,'key2'=> value);
Write forearch/for/ any loop to get the values, This is useful if you want to extract both key and values at the same time
foreach ($arr as $key=>$value) {
echo "$value <br>";
}
If you want to get only values then use array_values($arr)
You need to use array_values.
PHP Array
$arr = array("10 - 20" => 3,
"20 - 30" => 43,
"30 - 40" => 5,
"40 - 50" => 1,
"50 - 60" => 0,
"60 - 70" => 0
);
Array values from the array.
$arr2 = array_values($arr);
print_r($arr2);
Output Array
Array
(
[0] => 3
[1] => 43
[2] => 5
[3] => 1
[4] => 0
[5] => 0
)
If you need only the values as string then use implode.
echo implode(" , ", $arr2);
Result
3 , 43 , 5 , 1 , 0 , 0

PHP: Most frequent value in array

So I have this JSON Array:
[0] => 238
[1] => 7
[2] => 86
[3] => 79
[4] => 55
[5] => 92
[6] => 55
[7] => 7
[8] => 254
[9] => 9
[10] => 75
[11] => 238
[12] => 89
[13] => 238
I will be having more values in the actual JSON file. But by looking at this I can see that 238 and 55 is being repeated more than any other number. What I want to do is get the top 5 most repeated values in the array and store them in a new PHP array.
$values = array_count_values($array);
arsort($values);
$popular = array_slice(array_keys($values), 0, 5, true);
array_count_values() gets the count of the number of times each item appears in an array
arsort() sorts the array by number of occurrences in reverse order
array_keys() gets the actual value which is the array key in the results from array_count_values()
array_slice() gives us the first five elements of the results
Demo
$array = [1,2,3,4,238, 7, 86, 79, 55, 92, 55, 7, 254, 9, 75, 238, 89, 238];
$values = array_count_values($array);
arsort($values);
$popular = array_slice(array_keys($values), 0, 5, true);
array (
0 => 238,
1 => 55,
2 => 7,
3 => 4,
4 => 3,
)
The key is to use something like array_count_values() to tally up the number of occurrences of each value.
<?php
$array = [238, 7, 86, 79, 55, 92, 55, 7, 254, 9, 75, 238, 89, 238];
// Get array of (value => count) pairs, sorted by descending count
$counts = array_count_values($array);
arsort($counts);
// array(238 => 3, 55 => 2, 7 => 2, 75 => 1, 89 => 1, 9 => 1, ...)
// An array with the first (top) 5 counts
$top_with_count = array_slice($counts, 0, 5, true);
// array(238 => 3, 55 => 2, 7 => 2, 75 => 1, 89 => 1)
// An array with just the values
$top = array_keys($top_with_count);
// array(238, 55, 7, 75, 89)
?>

How to build a "child-parent" tree/nested array from database?

TABLE `people`
+----+------------+-------+
| sn | name | upper |
+----+------------+-------+
| 1 | Clement | 0 |
| 2 | Jean | 1 |
| 3 | Annie | 1 |
| 4 | Yuan | 2 |
| 5 | Mei | 2 |
| 6 | Blue | 3 |
| 7 | Yang | 5 |
| 8 | Lorinda | 0 |
+----+------------+-------+
The structure is like:
Clement
Jean
Yuan
Mei
Yang
Annie
Blue
Lorinda
The column upper states the upper person of himself/herself.
The problem is: How can I get a nested/multi-dimensional array from MySQL?
I thought I could use loops to fetch, but I failed to automated fetch all the lowers.
The array could be like this:
Array
(
[1]=>Array
(
[self]=>Clement
[2]=>Array
(
[self]=>Jean
[4]=>Array
(
[self]=>Yuan
)
[5]=>Array
(
[self]=>Mei
[7]=>Array
(
[self]=>Yang
)
)
)
[3]=>Array
(
[self]=>Annie
[6]=>Array
(
[self]=>Blue
)
)
)
[8]=>Array
(
[self]=>Lorinda
)
)
Since we don't know how many 'upper' persons does one have, the solution should be an automated function that build a complete array, not just for three or four dimension.
In other word, the function should deep into all the lower person from a top person.
Given your input as:
$input = array(
array('sn' => 1, 'name' => 'Clement', 'upper' => 0),
array('sn' => 2, 'name' => 'Jean', 'upper' => 1),
array('sn' => 3, 'name' => 'Annie', 'upper' => 1),
array('sn' => 4, 'name' => 'Yuan', 'upper' => 2),
array('sn' => 5, 'name' => 'Mei', 'upper' => 2),
array('sn' => 6, 'name' => 'Blue', 'upper' => 3),
array('sn' => 7, 'name' => 'Yang', 'upper' => 5),
array('sn' => 8, 'name' => 'Lorinda', 'upper' => 0),
);
using references you can build a tree with the following loop:
$map = array();
foreach ($input as $node) {
// init self
if (!array_key_exists($node['sn'], $map)) {
$map[$node['sn']] = array('self' => $node['name']);
}
else {
$map[$node['sn']]['self'] = $node['name'];
}
// init parent
if (!array_key_exists($node['upper'], $map)) {
$map[$node['upper']] = array();
}
// add to parent
$map[$node['upper']][$node['sn']] = & $map[$node['sn']];
}
print_r($map[0]);
demo: http://3v4l.org/vuVPu
Assuming the data is like this
$data = array(
array(1, 'Clement', 0),
array(2, 'Jean ', 1),
array(3, 'Annie ', 1),
array(4, 'Yuan ', 2),
array(5, 'Mei ', 2),
array(6, 'Blue ', 3),
array(7, 'Yang ', 5),
array(8, 'Lorinda', 0),
);
this recursive function might work:
function tree($data, $node) {
foreach($data as $e)
if($e[2] == $node[0])
$node['children'] []= tree($data, $e);
return $node;
}
Use it like this:
$tree = tree($data, array(0));
print_r($tree);
using a reference map
$input = array(
array('sn' => 1, 'name' => 'Clement', 'upper' => 0),
array('sn' => 2, 'name' => 'Jean', 'upper' => 1),
array('sn' => 3, 'name' => 'Annie', 'upper' => 1),
array('sn' => 4, 'name' => 'Yuan', 'upper' => 2),
array('sn' => 5, 'name' => 'Mei', 'upper' => 2),
array('sn' => 6, 'name' => 'Blue', 'upper' => 3),
array('sn' => 7, 'name' => 'Yang', 'upper' => 5),
array('sn' => 8, 'name' => 'Lorinda', 'upper' => 0),
);
$map = []; // map a reference by id for each item
foreach ($input as &$inp) {
$map[$inp['sn']] = &$inp;
}
foreach ($map as &$_inp) { // assign each item to its parent, with help of the map
if ($_inp['upper']) {
$map[$_inp['upper']]['children'] = &$map[$_inp['upper']]['children'] ?? [];
$map[$_inp['upper']]['children'][] = &$_inp;
}
}
$result = array_filter($map, fn($item) => !$item['upper']);
print_r($result);```

Categories