Array push not working in a function? PHP - php

I'm Trying to get 5 dates ($completion_date) into an array I have a list I'm looping through passing the $completion_date to the function below there are multiple instances of the same $completion_date in the list but I only want one of each in the array $completion_dates = []; so each time I search the array using array_search($completion_date, $completion_dates); and if the current $completion_date isn't there I want to add it to the array and if it is I want to modify $completions and $payouts at the same position in their respective arrays. My problem is array_push doesn't seem to push all the dates? only one?
And I've checked the if statement that array_push is in and it's running the else clause every time (as array_push isn't working to change that);
function sortResults($completion_date, $payout){
global $completion_dates, $completions, $payouts;
$completion_dates = [];
$completions = [0,0,0,0,0]; // not in use
$payouts = [0,0,0,0,0]; // not in use
// check is $completion_date is in $completion_dates array and get position if so.
$position = array_search($completion_date, $completion_dates);
if ($position) {
// update $payouts and $completions # same $position.
}else{
// add $completion_date to $completion_dates array.
array_push($completion_dates, $completion_date);
}
}
var_dump($completion_dates);
outputs: array(1) { [0]=> string(10) "22/01/2017" }
But should output four other dates "18/01/2017", "19/01/2017", "20/01/2017", "21/01/2017" as well?
the data i'm looping through is escaping the dates like so {"completion_date":"18\/01\/2017","0":"18\/01\/2017","payout":"13.20","1":"13.20"} not sure if it matters, it really shouldn't?

Because you overwrite $completion_dates each time in your function.
function sortResults($completion_date, $payout)
{
global $completion_dates, $completions, $payouts;
$completion_dates = []; <----------------------- HERE
$completions = [0, 0, 0, 0, 0]; // not in use
$payouts = [0, 0, 0, 0, 0]; // not in use
// check is $completion_date is in $completion_dates array and get position if so.
$position = array_search($completion_date, $completion_dates);
if ($position) {
// update $payouts and $completions # same $position.
} else {
// add $completion_date to $completion_dates array.
array_push($completion_dates, $completion_date);
}
}

Related

Artihmetical operations with json elements in Laravel

I try to make some operations with JSON files.
For example I intend to subtract them. But the problem is there can be different key elements.
$a1=[
{"cat":2,"total":1},
{"cat":11,"total":23},
{"cat":13,"total":30}
];
$a2=[
{"cat":2,"total":15},
{"cat":11,"total":13},
{"cat":15,"total":70},
{"cat":16,"total":40}
];
and result must be
$result=[
{"cat":2,"total":14},
{"cat":11,"total":-10},
{"cat":13,"total":-30},
{"cat":15,"total":70},
{"cat":16,"total":40}
]
I have tried to take elements in a loop but I could not.
would you please show me the way to make this work ?
First, the code:
<?php
$json1 = '[{"cat":2,"total":1},{"cat":11,"total":23},{"cat":13,"total":30}]';
$json2 = '[{"cat":2,"total":15},{"cat":11,"total":13},{"cat":15,"total":70},{"cat":16,"total":40}]';
$first = json_decode($json1, true);
$second = json_decode($json2, true);
$difference = [];
foreach ($second as $s) {
$key = null;
$f = array_filter($first, function($v, $k) use ($s, &$key){
$result = $v["cat"] === $s["cat"];
if ($result) $key = $k;
return $result;
}, ARRAY_FILTER_USE_BOTH);
$total = $s["total"] - (count($f) ? $f[$key]["total"] : 0);
$difference[]=["cat" => $s["cat"], "total" => $total];
}
foreach ($first as $f) {
$s = array_filter($second, function($v, $k) use ($f) {
return $v["cat"] === $f["cat"];
}, ARRAY_FILTER_USE_BOTH);
if (!count($s)) {
$difference[]=["cat" => $f["cat"], $total => -$f["total"]];
}
}
echo var_dump($difference); //I tested by echoing it out
Explanation:
I initialize two variables with the JSON inputs you have defined
I decode them both using json_decode and I set the second parameter to true to make sure they will be associative arrays
I loop the second
I initialize the key with null
I search for a match in the first using $s and $key so I will see these variables in the closure of the function
If I find such a match then I initialize $key with it
I subtract the first total (if exists) from the total
I add a new item with the matching category and the correct new total
I loop the first
I search a match in the second using $f
If no matches were found, I add the item with the matching category and negative total
In short, I loop the second and subtract the matching first if they exist, defaulting to 0 and then I loop the first to add the elements that do not have a match in the second.

Get x highest values from an array including identical values

I'm using the following code to retrieve the highest 3 numbers from an array.
$a = array(1,2,5,10,15,20,10,15);
arsort($a, SORT_NUMERIC);
$highest = array_slice($a, 0, 3);
This code correctly gives me the highest three numbers array(20,15,10); however, I'm interested in getting the highest 3 numbers including the ones that are identical. In this example, I'm expecting to get an array like array(10, 10, 15, 15, 20)
Might be simpler but my brain is tired. Use arsort() to get the highest first, count the values to get unique keys with their count and slice the first 3 (make sure to pass true to preserve keys):
arsort($a, SORT_NUMERIC);
$counts = array_slice(array_count_values($a), 0, 3, true);
Then loop those 3 and fill an array with the number value the number of times it was counted and merge with the previous result:
$highest = array();
foreach($counts as $value => $count) {
$highest = array_merge($highest, array_fill(0, $count, $value));
}
You can use a function like this:
$a = array(1,2,5,10,15,20,10,15); //-- Original Array
function get3highest($a){
$h = array(); //-- highest
if(count($a) >= 3){ //-- Checking length
$c = 0; //-- Counter
while ($c < 3 || in_array($a[count($a)-1],$h) ){ //-- 3 elements or repeated value
$max = array_pop($a);
if(!in_array($max,$h)){
++$c;
}
$h[] = $max;
}
sort($h); //-- sorting
}
return $h; //-- values
}
print_r(get3Highest($a));
Of course you can improve this function to accept a dinamic value of "highest" values.
The below function may be usefull
$a = array(1,2,5,10,15,20,10,15);
function getMaxValue($array,$n){
$max_array = array(); // array to store all the max values
for($i=0;$i<$n;$i++){ // loop to get number of highest values
$keys = array_keys($array,max($array)); // get keys
if(is_array($keys)){ // if keys is array
foreach($keys as $v){ // loop array
$max_array[]=$array[$v]; // set values to max_array
unset($array[$v]); // unset the keys to get next max value
}
}else{ // if not array
$max_array[]=$array[$keys]; // set values to max_array
unset($array[$keys]); // unset the keys to get next max value
}
}
return $max_array;
}
$g = getMaxValue($a,3);
Out Put:
Array
(
[0] => 20
[1] => 15
[2] => 15
[3] => 10
[4] => 10
)
You can modify it to add conditions.
I thought of a couple of other possibilities.
First one:
Find the lowest of the top three values
$min = array_slice(array_unique($a, SORT_NUMERIC), -3)[0];
Filter out any lower values
$top3 = array_filter($a, function($x) use ($min) { return $x >= $min; });
Sort the result
sort($top3);
Advantages: less code
Disadvantages: less inefficient (sorts, iterates the entire array, sorts the result)
Second one:
Sort the array in reverse order
rsort($a);
Iterate the array, appending items to your result array until you've appended three distinct items.
$n = 0;
$prev = null;
$top = [];
foreach ($a as $x) {
if ($x != $prev) $n++;
if ($n > 3) break;
$top[] = $x;
$prev = $x;
}
Advantages: more efficient (sorts only once, iterates only as much as necessary)
Disadvantages: more code
This gives the results in descending order. You can optionally use array_unshift($top, $x) instead of $top[] = $x; to get it in ascending order, but I think I've read that array_unshift is less efficient because it reindexes the array after each addition, so if optimization is important it would probably be better to just use $top[] = $x; and then iterate the result in reverse order.

Array with only 10 most recent values

I have an array with multiple elements. I want to keep only the 10 most recent values. So I am reversing the array in a loop, checking if the element is within the first 10 range and if not, I unset the element from the array.
Only problem is that the unset does not work. I am using the key to unset the element, but somehow this does not work. The array keeps on growing. Any ideas?
$currentitem = rand(0,100);
$lastproducts = unserialize($_COOKIE['lastproducts']);
$count = 0;
foreach(array_reverse($lastproducts) as $key => $lastproduct) {
if ($count <= 10) {
echo "item[$key]: $lastproduct <BR>";
}
else {
echo "Too many elements. Unsetting item[$key] with value $lastproduct <BR>";
unset($lastproducts[$key]);
}
$count = $count + 1;
}
array_push($lastproducts, $currentitem);
setcookie('lastproducts', serialize($lastproducts), time()+3600);
I'd use array_slice ( http://php.net/array_slice ) perhaps like:
$lastproducts = unserialize($_COOKIE['lastproducts']);
// add on the end ...
$lastproducts[] = $newproduct;
// start at -10 from the end, give me 10 at most
$lastproducts = array_slice($lastproducts, -10);
// ....
You can use array_splice($input, $offset) function for this purpose.
$last_items_count = 10;
if(count($lastproducts) >= $last_items_count) {
$lastproducts = array_splice($lastproducts, count($lastproducts) - $last_items_count);
}
var_dump($lastproducts);
I hope this code helps.
For more information, here is the documentation:
http://php.net/manual/en/function.array-splice.php
I think a better way to select last 10 is:
$selection = array();
foreach(array_reverse($lastproducts) as $key => $lastproduct) {
$selection[$key] = $lastproduct;
if (count($selection)>=10) break;
}
Finally, $selection will have last 10 (or less) products.
Works great using array_splice and array_slice, thanks! :)
$lastproducts = unserialize($_COOKIE['lastproducts']);
// remove this product from array
$lastproducts = array_diff($lastproducts, array($productid));
// insert product on first position in array
array_splice($lastproducts, 0, 0, $productid);
// keep only first 15 products of array
$lastproducts = array_slice($lastproducts, 0, 15);

PHP get ranges of same values from array

Is there any way to get the key range of same values and make a new array?
Let's say we have an Array Like this in php :
$first_array = ['1'=>'a','2'=>'a','3'=>'a','4'=>'b','5'=>'b','6'=>'a','7'=>'a'];
How can i get this array? Is there any function for this?
$second_array = ['1-3'=>'a','4-5'=>'b','6-7'=>'a'];
Loop through it, extract the keys, generate the ranges and insert to the new array -
$first_array = ['1'=>'a','2'=>'a','3'=>'a','4'=>'b','5'=>'b'];
$flip = array();
foreach($first_array as $key => $val) {
$flip[$val][] = $key;
}
$second_array = [];
foreach($flip as $key => $value) {
$newKey = array_shift($value).' - '.end($value);
$second_array[$newKey] = $key;
}
Output
array(2) {
["1 - 3"]=>
string(1) "a"
["4 - 5"]=>
string(1) "b"
}
regarding your first question you can get range of each value using foreach() loop.
$first_array = ['1'=>'a','2'=>'a','3'=>'a','4'=>'b','5'=>'b'];
foreach($first_array as $key=>$value)
{
//do your coding here, $key is the index of the array and $value is the value at that range, you can use that index and value to perform array manipulations
}
Regarding your second question it not exactly clear what are trying to implement there. But what ever you want to do like creating a new array with modified index and other things can be done within this foreach() loop itself
I hope this helps you.
If someone is still looking for an answer, here is what I did.
Given the array
$first_array = ['0'=>'a',
'1'=>'a',
'2'=>'a',
'3'=>'a',
'4'=>'a',
'5'=>'b',
'6'=>'b',
'7'=>'a',
'8'=>'a']
I build a multidimensional array, in which each element is an array of three more elements:
[0] - The value in the first array
[1] - The key where the value starts repeating
[2] - The last key where the value stops repeating
The code
$arrayRange = [];
for($i = 0; $i < count($first_array); $i++){
if(count($arrayRange) == 0){
// The multidimensional array is still empty
$arrayRange[0] = array($first_array[$i], $i, $i);
}else{
if($first_array[$i] == $arrayRange[count($arrayRange)-1][0]){
// It's still the same value, I update the value of the last key
$arrayRange[count($arrayRange)-1][2] = $i;
}else{
// It's a new value, I insert a new array
$arrayRange[count($arrayRange)] = array($first_array[$i], $i, $i);
}
}
}
This way you get a multidimensional array like this:
$arrayRange[0] = array['a', 0, 4];
$arrayRange[1] = array['b', 5, 6];
$arrayRange[2] = array['a', 7, 8];

Json_encode - converting an array into a json object

I am currently fetching values from mysql table. The values are grabbed from a foreach loop. Then after the loop is done the array is converted into a json object. But I am having difficulties getting the json format in order to use with another api. My loop only display one result when there are two. Also I have a function that returns a hexadecimal value which is returning null when I call it inside the loop. How could I get those values in the format shown below?
header("Content-type: application/json");
//get the course list
$education_query = $db_con->prepare("SELECT a.type, COUNT(1) AS cnt
FROM academy a
GROUP BY a.type");
$education_query->execute();
$data = $education_query->fetchAll();
$output = array();
foreach ($data as $row) {
//$type = ;
$output["valueField"] = $row["type"];
$output["name"] = $row["type"];
$output["color"] = hexcode();
} // foreach ($data as $row) {
echo json_encode(array($output));
Current Result:
[{"valueField":"Upper-Secondary","name":"Upper-Secondary","color":null}]
Desired Result:
[{
valueField: "Post-Secondary",
name : "Post-Secondary",
color: "#40ae18"
},
{
valueField: "Upper-Secondary",
name : "Upper-Secondary",
color: "#aaab4b"
}]
EDIT(adding hexcode function):
function hexcode()
{
$min = hexdec("000000"); // result is 0 and sets the min-value for mt_rand
$max = hexdec("FFFFFF"); // result is 16777215 and sets the max-value for mt_rand
$random = mt_rand($min, $max); // creates a radom number between 0 and 16777215
$random_hex = dechex($random); // transforms the random number into a Hex-Code
// now the test, if the result has 6 chars
if (strlen($random_hex) != "6") // sometimes it returns an only 5, or less, char Hex-Code,
hexcode(); // so the function has to be repeat
else
echo $random_hex; // returns the Hex-Code
}
$output needs to be an array of arrays.
$addToOutput = array();
$addToOutput["valueField"] = $row["type"];
// add other fields
$output[] = $addToOutput;
your loop is displying one results because you're overwriting the array keys every time.
you can change those 3 lines
$output["valueField"] = $row["type"];
$output["name"] = $row["type"];
$output["color"] = hexcode();
to
$output[]["valueField"] = $row["type"];
$output[]["name"] = $row["type"];
$output[]["color"] = hexcode();
can you post the hexcode() function ?
EDIT
no need for all this code, you can use this :
function hexcode(){
return sprintf("#%02X%02X%02X", mt_rand(0, 255), mt_rand(0, 255), mt_rand(0,255));
}

Categories