Function not returning a result [duplicate] - php

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
Here is a function in PHP that generates a random number between 1 and 15 and store that number in a array and keep calling itself to repeat until the array contains five elements, at which point, you can make it either print/echo out the elements of the array or return the array. My problem is that when I try to get it to return the array and assign it to the variable $result, I get nothing. Any ideas as to what's going on?
$storenumbers = array();
function storemynumbers($storenumbers){
$number = rand(1,15);
if(count($storenumbers) == 5){
echo "Done<br/>";
print_r($storenumbers);
//return $storenumbers;
}else{
echo $number."<br/>";
$storenumbers[] = $number;
storemynumbers($storenumbers);
}
}
//$result = storemynumbers($storenumbers);
//print_r($result);
storemynumbers($storenumbers);

Because you are only returning anything on the last run, which gets passed back to the next-to-last run, which is then dropped.
In your else block, try adding return in front of storemynumbers($storenumbers). This should pass the return value all the way back down the chain.
That said, why can't you just do:
$storenumbers = Array();
for( $i=0; $i<5; $i++) $storenumbers[] = rand(1,15);
print_r($storenumbers);

becouse you need to pass parameter by reference(& before parameter): like this:
function storemynumbers(&$storenumbers){
}
By default variables are local copy, so they not visible outside function.

missing return on the recursion. would be my guess.
$storenumbers = array();
function storemynumbers($storenumbers){
$number = rand(1,15);
if(count($storenumbers) == 5){
echo "Done<br/>";
print_r($storenumbers);
return $storenumbers;
}else{
echo $number."<br/>";
$storenumbers[] = $number;
return storemynumbers($storenumbers);
}
}
$result = storemynumbers($storenumbers);
print_r($result);

This is a easy way to create a array of $max random number between 1 and 15.
function storemynumbers($max, $start, $end) {
$store = array();
for( $i=0; $i<$max; $i++) {
$store[] = rand($start, $end);
}
return $store;
}
$result = storemynumbers(5, 1, 15);
print_r($result);
You could also use a reference to a variable

Related

PHP create unique value compared to values from object

I need to create a unique value for $total, to be different from all other values from received object. It should compare total with order_amount from object, and then if it is the same, it should increase its value by 0.00000001, and then check again through that object to see if it matches again with another order_amount. The end result should be a unique value, with minimal increase compared to the starting $total value. All values are set to have 8 decmal places.
I have tried with the following but it won't get me the result i need. What am i doing wrong?
function unique_amount($amount, $rate) {
$total = round($amount / $rate, 8);
$other_amounts = some object...;
foreach($other_amounts as $amount) {
if ($amount->order_amount == $total) {
$total = $total + 0.00000001;
}
}
return $total;
}
<?php
define('EPSILON',0.00000001);
$total = 4.00000000;
$other_amounts = [4.00000001,4.00000000,4.00000002];
sort($other_amounts);
foreach($other_amounts as $each_amount){
if($total === $each_amount){ // $total === $each_amount->order_amount , incase of objects
$total += EPSILON;
}
}
var_dump($total);
OUTPUT
float(4.00000003)
You may add an additional break if $total < $each_amount to make it a bit more efficient.
UPDATE
To sort objects in $other_amounts based on amount, you can use usort.
usort($other_amounts,function($o1,$o2){
if($o1->order_amount < $o2->order_amount ) return -1;
else if($o1->order_amount > $o2->order_amount ) return 1;
return 0;
});
Ok, here's the solution I came up with. First I created a function to deliver random objects with random totals so I could work with, unnecessary for you but useful for the sake of this test:
function generate_objects()
{
$outputObjects = [];
for ($i=0; $i < 100; $i++) {
$object = new \stdClass();
$mainValue = random_int(1,9);
$decimalValue = random_int(1,9);
$object->order_amount = "{$mainValue}.0000000{$decimalValue}";
$outputObjects[] = $object;
}
return $outputObjects;
}
And now for the solution part, first the code, then the explanation:
function unique_amount($amount, $rate) {
$total = number_format(round($amount / $rate, 8), 4);
$searchTotal = $total;
if (strpos((string) $searchTotal, '.') !== false) {
$searchTotal = str_replace('.', '\.', $searchTotal);
}
$other_amounts = generate_objects();
$similarTotals = [];
foreach($other_amounts as $amount) {
if (preg_match("/^$searchTotal/", $amount->order_amount)) {
$similarTotals[] = $amount->order_amount;
}
}
if (!empty($similarTotals)) {
rsort($similarTotals);
$total = ($similarTotals[0] + 0.00000001);
}
// DEBUG
//echo '<pre>';
//$vars = get_defined_vars();
//unset($vars['other_amounts']);
//print_r($vars);
//die;
return $total;
}
$test = unique_amount(8,1);
echo $test;
I decided to use RegEx to find the amounts that starts with the ones I provided. Since in the exercise I provided only integers with 1-9 in the last decimal case, I tracked them and added them to one array $similarTotals.
Then I sorted this array, if not empty, descending by the values, got the first item and incremented by 0.00000001.
So, finally, returning either the $total (assuming nothing was found) or the incremented first item in the array.
PS. I did not expect this code to be this big but, well...
You can see the test here: https://3v4l.org/WGThI

Recursive cURL function php [duplicate]

This question already has answers here:
How to use return inside a recursive function in PHP
(4 answers)
Closed 9 months ago.
I am having a problem with a php function, it is a recursive function - which seems to work, because if i dump the array I see the items are added to the array. But when I want to return the array I get a null.
The api function is a http curl wrapper function which handles the api call - that works fine, also the $arr get's filled with the db_address items - but the return doesn't return the array - if I var_dump the result I get a Null, if I print_r the result I just get a 1.
function get_all_db_addresses($arr, $skip){
if(!isset($arr)){
$arr = [];
}
if(!isset($skip)){
$skip = 0;
}
$db_addresses = json_decode(db_api('GET', 'DbAddress?$skip=' . $skip), true);
$arr = array_merge($arr, $db_addresses['value']);
if(!array_key_exists('#odata.nextLink', $db_addresses)){
return $arr;
} else {
$skip += 20;
get_all_db_addresses($arr, $skip);
}
}
Am i doing something wrong here? I don't see what i'm doing wrong here..
You have 2 problems:
You don't have return statement when performing recursive call
In case you perform array_merge with null, you will get null
Check this:
function get_all_db_addresses($arr = array(), $skip = 0)
{
$db_addresses = json_decode(db_api('GET', 'DbAddress?$skip=' . $skip), true);
if (isset($db_addresses['value'])) {
$arr = array_merge($arr, $db_addresses['value']);
}
if (array_key_exists('#odata.nextLink', $db_addresses)) {
return get_all_db_addresses($arr, $skip + 20);
}
return $arr;
}
You need to create global variable and merge next array to it
function get_all_db_addresses($skip)
{
if(!isset($skip)){
$skip = 0;
}
$db_addresses = json_decode(db_api('GET', 'DbAddress?$skip=' . $skip), true);
$arr = array();
if(!array_key_exists('#odata.nextLink', $db_addresses)){
$arr = array_merge($arr, $db_addresses['value']);
} else {
$skip += 20;
$arr = array_merge($db_addresses['value'], get_all_db_addresses($skip));
}
return $arr;
}
Not sure, but possiblly it works as I can't test your data
Try this:
function get_all_db_addresses($arr = [], $skip = 0){
$db_addresses = json_decode(db_api('GET', 'DbAddress?$skip=' . $skip), true);
$arr = array_merge($arr, $db_addresses['value']);
if(!array_key_exists('#odata.nextLink', $db_addresses)){
return $arr;
} else {
$skip += 20;
return get_all_db_addresses($arr, $skip);
}
}
You have to add return statment for recursive call.
And tip: don't check if parameter isset - set for it default value.
Problems in your code:
Your function argument should be passed reference if you want to change the value of argument References Explained.
You should always return a value (with specified type) if you expect the function to.
Default argument value can be set directly in new PHP versions, but this should not break your code, just coding style.
Solution:
Your function should be modified to this to work correctly (haven't tested):
function &get_all_db_addresses(&$arr = [], $skip = 0) {
// ...
if(array_key_exists('#odata.nextLink', $db_addresses)){
get_all_db_addresses($arr, $skip + 20);
}
return $arr;
}

php array, to check if a value at key is set or not and update accordingly

I initialize a php array named $present, the purpose of this array is to hold the value of 1 if a name is present or zero if the name is absent. i have a name array of size 10. below is the code mentioned, but it is not working.
$present = Array();
for($i=0;$i<=10;$i++){
if(!isset($present[$name[$i]])) {
$present[$name] = 1;
}
else echo $present[$name[$i]];
}
i have also tried this :
$present = Array();
for($i=0;$i<=10;$i++){
if(empty($present[$name[$i]])) {
$present[$name] = 1;
}
else echo $present[$name[$i]];
}
please help thanks!
I think this may be what you are looking for. You're missing the $i when setting it to 1.
$present = array();
for($i=0;$i<=10;$i++){
if(!isset($present[$name[$i]])) {
$present[$name[$i]] = 1;
}
else echo $present[$name[$i]];
}
Should be:
$present = Array();
for($i=0;$i<10;$i++){
if(!isset($present[$name[$i]])) {
$present[$name[$i]] = 1;
}
else echo $present[$name[$i]];
}
I'm not sure exactly what you're trying to do here, but if you just want to keep track of whether a name is present or not, you could just make $present be an array of names, and then use in_array.
$present = array('John', 'Paul', 'George');
echo in_array('John', $present); # returns 1
echo in_array('MacArthur', $present); #returns 0

Return an array from PHP function to Smarty

At the risk of self-embarrassment, could anyone tell me how to use return here:
function dayCount() {
for ($dayBegin = 1; $dayBegin < 32; $dayBegin++)
{
"<option value=\"".$dayBegin."\">".$dayBegin."</option>";
}
}
My issue is that I am passing this function to Smarty via
$dayCount = dayCount();
$smarty->assign('dayCount', $dayCount);
and
{$dayCount}
but instead the HTML is going straight to the buffer, right before <html> (thanks Hamish), not inside the HTML element I want.
Any help on this?
You need to build up the return statement
function dayCount() {
$return = array();
for ($dayBegin = 1; $dayBegin < 32; $dayBegin++)
{
$return[] = "<option value=\"".$dayBegin."\">".$dayBegin."</option>";
}
return $return;
}
Although this is building up an array like you asked. When outputting it, you would need to implode it.
implode('', $dayCount);
Or otherwise, build up a string instead of an array.

How do I store the results of this recursive function?

I have the following PHP code which works out the possible combinations from a set of arrays:
function showCombinations($string, $traits, $i){
if($i >= count($traits)){
echo trim($string) . '<br>';
}else{
foreach($traits[$i] as $trait){
showCombinations("$string$trait", $traits, $i + 1);
}
}
}
$traits = array(
array('1','2'),
array('1','2','3'),
array('1','2','3')
);
showCombinations('', $traits, 0);
However, my problem is that I need to store the results in an array for processing later rather than just print them out but I can't see how this can be done without using a global variable.
Does anyone know of an alternative way to achieve something similar or modify this to give me results I can use?
Return them. Make showCombinations() return a list of items. In the first case you only return one item, in the other recursive case you return a list with all the returned lists merged. For example:
function showCombinations(...) {
$result = array();
if (...) {
$result[] = $item;
}
else {
foreach (...) {
$result = array_merge($result, showCombinations(...));
}
}
return $result;
}
In addition to the other answers, you could pass the address of an array around inside your function, but honestly this isn't nearly the best way to do it.
Using the variable scope modifier static could work. Alternatively, you could employ references, but that's just one more variable to pass. This works with "return syntax".
function showCombinations($string, $traits, $i){
static $finalTraits;
if (!is_array($finalTraits)) {
$finalTraits = array();
}
if($i >= count($traits)){
//echo trim($string) . '<br>';
$finalTraits[] = $string;
} else {
foreach($traits[$i] as $trait){
showCombinations("$string$trait", $traits, $i + 1);
}
}
return $finalTraits;
}
$traits = array(
array('1','2'),
array('1','2','3'),
array('1','2','3')
);
echo join("<br>\n",showCombinations('', $traits, 0));
Of course, this will work as expected exactly once, before the static nature of the variable catches up with you. Therefore, this is probably a better solution:
function showCombinations($string, $traits, $i){
$finalTraits = array();
if($i >= count($traits)){
$finalTraits[] = $string;
} else {
foreach($traits[$i] as $trait){
$finalTraits = array_merge(
$finalTraits,
showCombinations("$string$trait", $traits, $i + 1)
);
}
}
return $finalTraits;
}
although the solution by Lukáš is the purest as it has no side effects, it may be ineffective on large inputs, because it forces the engine to constantly generate new arrays. There are two more ways that seem to be less memory-consuming
have a results array passed by reference and replace the echo call with $result[]=
(preferred) wrap the whole story into a class and use $this->result when appropriate
the class approach is especially nice when used together with php iterators
public function pageslug_genrator($slug,$cat){
$page_check=$this->ci->cms_model->show_page($slug);
if($page_check[0]->page_parents != 0 ){
$page_checks=$this->ci->page_model->page_list($page_check[0]->page_parents);
$cat[]=$page_checks['re_page'][0]->page_slug;
$this->pageslug_genrator($page_checks['re_page'][0]->page_slug,$cat);
}
else
{
return $cat;
}
}
this function doesnt return any value but when i m doing print_r $cat it re
store the results in a $_SESSION variable.

Categories