Jump to content

Recommended Posts

Hi,

 

Consider this array:

Array
(
    [1] => 100
    [11] => 90
    [100] => 30
    [200] => 20
    [400] => 10
    [1000] => 5
)

 

What I need help with is to write a function so that for example I could getValue($key) where $key = 4 and the function will first try to find a $key of 4, if found return the value.

If it cannot find the $key = 4 then it will calculate what 4's value would have been based on scale. So in this case $key = 4 would return 97

 

Any ideas? It's a bit tricky to do without a lot of loops especially when they keys are not your usual index.

 

Basically it needs to return a calculated value for a given $key based on the scale of it's upper / minimum neighbors.

Link to comment
https://forums.phpfreaks.com/topic/196537-calculate-missing-array-key-values/
Share on other sites

That would only work if you had a set formula to work off of. If each set will have a different formula, then writing a static function to calculate possible results would be near impossible.  The best route would be to write a function that will take in 2 inputs: the array, and the formula to calculate the missing portions of the array.

That would only work if you had a set formula to work off of. If each set will have a different formula, then writing a static function to calculate possible results would be near impossible.  The best route would be to write a function that will take in 2 inputs: the array, and the formula to calculate the missing portions of the array.

 

So you're saying even if I know the min / max values (neighbors that exist) for a given $key and therefore knowing how many missing keys there are in between those min / max I can't calculate it?

Array
(
    [1] => 100
    [11] => 90
    [100] => 30
    [200] => 20
    [400] => 10
    [1000] => 5
)

How do you calculate that 4 will be 94, and 1000 will be 5?  Is there a way to calculate it?  That's the problem. I don't see a pattern.

Array
(
    [1] => 100
    [11] => 90
    [100] => 30
    [200] => 20
    [400] => 10
    [1000] => 5
)

How do you calculate that 4 will be 94, and 1000 will be 5?  Is there a way to calculate it?  That's the problem. I don't see a pattern.

 

Sorry perhaps I haven't explained the problem as much.

 

The array above is pre-populated by a user. Basically $key is a quantity and $value is a percent. So as the $key gets higher the $value gets lower. The user decides for x quantity will have x value and knows that as the quantity goes up the value will go down. What I need is based on the user's predefined array is to calculate what the missing $key would be based on what is present. So I calculated a return value of 97 based on the min / max and the difference of the $key 4.

 

Eg: The process would calculate based on the Min being 1 (value of 100) and the Max being 11 (value of 90) therefore on a scale below:

1            2            3            |4|            5            6            7            8            9            10            11

100      99          98       |97|          96          95          94          93          92          94            90

 

If  a user used a $key of say 116 then it would have to calcule based on a Min of 100 (value of 30) and a Max of 200 (value of 20)

quick and .....

<?php

$a= array();

$a[1]=100;
$a[11]=90;
$a[100]=30;
$a[200]=20;
$a[400]=10;
$a[1000]=5;

$f=0;
$pf='';
$pv='';
foreach ($a as $f => $value) {
        echo "$f, $value, ". "<br>\n";
        if ($pf!='')
        {
                for ($i=$pf+1; $i<$f; $i++)
                {
                        $t1=($i-$pf)/($f-$pf);
                        $t2 = $t1*($value-$pv)+$pv ;
                        echo "** $i, ". $t2 . " <br>\n";
                }
        }
        $pf=$f;
        $pv=$value;
}

?>

output:
[code]
1, 100, <br>
11, 90, <br>
** 2, 99 <br>
** 3, 98 <br>
** 4, 97 <br>
** 5, 96 <br>
** 6, 95 <br>
** 7, 94 <br>
** 8, 93 <br>
** 9, 92 <br>
** 10, 91 <br>
100, 30, <br>
** 12, 89.325842696629 <br>
** 13, 88.651685393258 <br>
** 14, 87.977528089888 <br>
** 15, 87.303370786517 <br>
** 16, 86.629213483146 <br>
** 17, 85.955056179775 <br>
........... etc....

[/code]

quick and .....

<?php

$a= array();

$a[1]=100;
$a[11]=90;
$a[100]=30;
$a[200]=20;
$a[400]=10;
$a[1000]=5;

$f=0;
$pf='';
$pv='';
foreach ($a as $f => $value) {
        echo "$f, $value, ". "<br>\n";
        if ($pf!='')
        {
                for ($i=$pf+1; $i<$f; $i++)
                {
                        $t1=($i-$pf)/($f-$pf);
                        $t2 = $t1*($value-$pv)+$pv ;
                        echo "** $i, ". $t2 . " <br>\n";
                }
        }
        $pf=$f;
        $pv=$value;
}

?>

output:
[code]
1, 100, <br>
11, 90, <br>
** 2, 99 <br>
** 3, 98 <br>
** 4, 97 <br>
** 5, 96 <br>
** 6, 95 <br>
** 7, 94 <br>
** 8, 93 <br>
** 9, 92 <br>
** 10, 91 <br>
100, 30, <br>
** 12, 89.325842696629 <br>
** 13, 88.651685393258 <br>
** 14, 87.977528089888 <br>
** 15, 87.303370786517 <br>
** 16, 86.629213483146 <br>
** 17, 85.955056179775 <br>
........... etc....

[/code]

 

Ok and rather than actually populating the whole array is there a way just to pull the one value please? Remembering that the "scale" changes between each populated min / max

Hey thank you for answering the question in my thread, I'm just wondering - How might you do this so rather than having a lot of calculations to populate the entire array (sometimes 1000+) how might you go about it to just calculate the one value?

 

Eg: getValue($key); and have it return the value without having to loop and populate the entire thing?

This is what I have as part of the method to find the $key that does not exist. Any way this can be improved? It seems a bit more long winded than your example jskywalker.

 

// $amount is the $key of the array
$amount = 40;

$scalePercents = array();
$scalePercents[5] = 90;
$scalePercents[10] = 85;
$scalePercents[20] = 70;
$scalePercents[30] = 60;
$scalePercents[50] = 50;
$scalePercents[100] = 30;
$scalePercents[200] = 20;
$scalePercents[400] = 10;
$scalePercents[1000] = 5;

if (!array_key_exists($amount, $scalePercents)) {
echo '<hr />Amount Does not exist <br />';
$percentKeys = array_keys($scalePercents);

// $scaleRangeMin Value $amount = 1 or defaults to 100
$scaleRangeMin = ($scalePercents[1]) ? $scalePercents[1] : 100;

// $scaleRangeMax Value $amount = $maxAmount or defaults to 100
$maxAmount = end($percentKeys);
$scaleRangeMax = ($scalePercents[$maxAmount]) ? $scalePercents[$maxAmount] : 100;

// Loop from $amount until 1
for ($iMin = $amount; $iMin > 1; $iMin--) {
	if (array_key_exists($iMin, $scalePercents)) {
		$scaleRangeMin = $scalePercents[$iMin];
		break;
	}
}

// Loop from $amount until $maxAmount
for ($iMax = $amount; $iMax < $maxAmount; $iMax++) {
	if (array_key_exists($iMax, $scalePercents)) {
		$scaleRangeMax = $scalePercents[$iMax];
		break;
	}
}

echo 'Min Discount is: ' . $scaleRangeMin . '% of Price <br />';
echo 'Max Discount is: ' . $scaleRangeMax . '% of Price based on Quantity: ' . $amount . '<hr />';

// Calculate further
$difference = $iMax - $iMin;
$percentToScale = $scaleRangeMin - $scaleRangeMax;
$eachPercent = ($difference > 0) ? $percentToScale / $difference : 1;
$percentToSubtract = $amount - $iMin;
$finalPercent = $scaleRangeMin - $eachPercent * $percentToSubtract;

echo 'Difference: ' . $difference . '<br />Percent to Scale: ' . $percentToScale . '%';
echo '<br />Each Percent: ' . $eachPercent . '%<br />Quantity of: ' . $amount . ' is ' . $finalPercent . '%<hr />';

// Create $amount => $percent to calculate Price
$scalePercents[$amount] = $finalPercent;
}

------------------------------------------------------------------------------------------------------------------------------------------------------
Amount Does not exist 
Min Discount is: 60% of Price 
Max Discount is: 50% of Price based on Quantity: 40
------------------------------------------------------------------------------------------------------------------------------------------------------
Difference: 20
Percent to Scale: 10%
Each Percent: 0.5%
Quantity of: 40 is 55%
------------------------------------------------------------------------------------------------------------------------------------------------------

Hey thank you for answering the question in my thread, I'm just wondering - How might you do this so rather than having a lot of calculations to populate the entire array (sometimes 1000+) how might you go about it to just calculate the one value rather than populating the entire array?

 

Its in the code above, try to read, and understad it, it does it 1000+ times........

Hey thank you for answering the question in my thread, I'm just wondering - How might you do this so rather than having a lot of calculations to populate the entire array (sometimes 1000+) how might you go about it to just calculate the one value rather than populating the entire array?

 

Its in the code above, try to read, and understad it, it does it 1000+ times........

 

Yup understand it now :) Very clever! Thank you very much :D Heaps cleaner than my old.

                        $pa = $pv = 0;
		foreach ($scalePercents as $a => $value) {
			// Loop if picked $amount
			if ($pa != 0) {
				for ($i = $pa + 1; $i < $a; $i++) {
					if ($i == $amount) {
						$t1 = ($i - $pa) / ($a - $pa);
						$t2 = $t1 * ($value - $pv) + $pv;
						$scalePercents[$amount] = $t2;
						echo '** ' . $i . ' => ' . $t2 . '%<br />';
						break 2;
					}
				}
			}
	        // Set picked $amount
			$pa = $a;
			// Set picked $value
	        $pv = $value;
			echo $a . ' => ' . $value . '%<br />';
		}

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.