So, I need to find out the highest possible difference between any two random values of an indexed array and I am not sure if my answer is correct, coz you know it's way too simple for the weight of this question:
function($array)
{
asort($array);
$diff = $array(sizeof($array) - 1) - $array(0);
return $diff;
}
I am sure this is correct, then again I always have my doubts!
You are right that the largest difference you will find is between the maximum value and the minimum value. However, you could achieve this more efficiently (O(N) instead of O(N log N)) by simply scanning the array to find the min and max values without sorting.
Just to wrap your head around the logic, here is a manual way of doing this:
$myarray = array(
'this' => 2,
'that' => 14,
'them' => -5,
'other' => 200,
'nothing' => 42,
'somethingelse' => 1,
'you' => 10,
'me' => 30);
foreach ($myarray as $key => $value) {
if (!isset ($min) || $value < $min) { $min = $value; }
if (!isset ($max) || $value > $max) { $max = $value; }
}
$diff = $max - $min;
echo $diff;
Related
I need a function in PHP where I have a number I want to subtract from 3 items in an array but one after the other decreasing the original number and if it depletes one of the 3 items moves on to the next.
for example if these are my starting variable and array
$original_number = 15;
$pots = [
'pot_1' => 10,
'pot_2' => 10,
'pot_3' => 10,
];
Lets say I want to subtract 15 from all three pots items one after the other leaving a pot item at 0 (if it goes in to minus) and then moving on to the next pot until the original number is depleted.
So that would mean this would be the outcome...
$original_number = 0;
$pots = [
'pot_1' => 0,
'pot_2' => 5,
'pot_3' => 10,
];
function substract($number, $array) {
for($array as $key => $value) {
if($value > $number) {
$array[$key] = $value - $number;
$number = 0;
return $number;
} else {
$number -= $value;
$array[$key] = 0;
}
}
return $number;
}
You could then have $original_number = substract($original_number, $pots)
I have an associative array from which I need a new array to be created. I am targeting the peak values for the new array. For a value to be selected to the new array, it needs to be higher than both the previous and the next value in the array.
I have searched the net and found a function that could handle the situation for indexed arrays - but not for associative arrays. Here is what I would like:
$array = array('a' => 0, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3);
$result = array('b' => 2, 'e' => 3);
The function usable for indexed arrays look like this:
$a = array(0, 2, 1, 2, 3);
$b = array_filter($a, function($v, $k) use($a) {
return $k > 0 && $v > $a[$k-1] && $k + 1 < count($a) && $v > $a[$k+1];
}, ARRAY_FILTER_USE_BOTH );
This function doesn't include the last value either.
You should change the condition if you really want to get border items. But an approach could be to use the array of keys to get prev and next items
$array = array('a' => 0, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3);
$keys = array_keys($array);
$b = array_filter($array, function($v, $k) use($array, $keys) {
$k = array_search($k, $keys);
return $k > 0 && $v > $array[$keys[$k-1]] && $k + 1 < count($keys) && $v > $array[$keys[$k+1]];
}, ARRAY_FILTER_USE_BOTH );
print_r($b);
This can be done with zero iterated function calls.
Before looping declare a lookup array by assigning indices to the input array's keys -- array_keys().
Then in the loop use conditional fallback values and null coalescing when an attempt to access a non-existent element occurs.
($i ? $array[$keys[$i - 1]] : $array[$key] - 1) means: if $i is not zero, then access the value from the input array by its key which is one position before the current key. Otherwise, $i equals zero which means there is no earlier value so fallback to the current value minus one to guarantee it will be less in the comparison.
($array[$keys[$i + 1] ?? -1] ?? $array[$key] - 1) means: try to access the next key in the lookup array, if it does not exist, use negative one which is guaranteed not to exist. By effect, when $i is that last index in the loop, there will be no next key, so fallback to the current value minus one again.
This should always outperform any script that makes iterated function calls.
Code: (Demo)
$array = ['a' => 0, 'b' => 2, 'c' => 1, 'd' => 2, 'e' => 3];
$keys = array_keys($array);
foreach ($keys as $i => $key) {
if ($array[$key] > ($i ? $array[$keys[$i - 1]] : $array[$key] - 1)
&& $array[$key] > ($array[$keys[$i + 1] ?? -1] ?? $array[$key] - 1)
) {
$result[$key] = $array[$key];
}
}
var_export($result);
Output:
array (
'b' => 2,
'e' => 3,
)
Alternatively, if you want to mutate the input array, you can call unset() in the loop and simply invert the conditional logic.
I worked #splash58. Thank you. I have none the less tried something myself which also worked - but I don't know which solution is most effective.
$result = array();
$value1 = NULL;
foreach (array_reverse($array) as $key => $value) {
if ($value > $value1) {
$result[$key] = $value;
}
$value1 = $value;
}
and is '$value1 = NULL' this necessary?
Im not sure if ive wrote the question properly but ill elaborate more on what i need.
I have two objects which i need to change to array and they have keys 1,2,3 but they have different values i need to subtract the values from the array where the keys are the same, I hope this makes sense.
Things ive tried to far
Push them both to 1 array and do the math from there (can't figure out how to do this)
use array_diff to find the difference in the arrays but didn't work.
All help appreciated any more information needed will be provided
Example Arrays:
Array 1
1 => 300.00,
2 => 300.00,
3 => 300.00
Array 2
1 => 200.00,
2 => 200.00,
3 => 200.00
Desired output
1 => 100.00,
2 => 100.00,
3 => 100.00
The best option for this seems to be a for loop
$arr1 = [300, 300, 300];
$arr2 = [200, 200, 200];
$arr_length = sizeof($arr1) -1;
$minus_arr = [];
for($i = 0; $i <= $arr_length; $i++){
$minus = $arr1[$i] - $arr2[$i];
array_push($minus_arr, $minus);
}
print_r($minus_arr);
I took for granted your given arrays above, it sounds like the arrays you're using are either not the same size or have strings or nulls in them so check for an int first.
<?php
$arr1 = [300, 300, 300];
$arr2 = [200, 200, 200];
$arr_length = sizeof($arr1) -1;
$minus_arr = [];
for($i = 0; $i <= $arr_length; $i++){
if(is_int($arr1[$i]) && is_int($arr2[$i])){
$minus = $arr1[$i] - $arr2[$i];
array_push($minus_arr, $minus);
}
}
print_r($minus_arr);
I hope I do not misunderstand your question.
My method is iterate through 2 arrays, and whenever their keys are the same, do the operation. Here is a example:
function diff($arr1, $arr2) {
$result = [];
foreach($arr1 as $key1 => $value1) {
foreach($arr2 as $key2 => $value2) {
if ($key1 == $key2) {
$result[$key1] = $value1 - $value2;
}
}
}
return $result;
}
I see there is Laravel in your tag, if you're using laravel, I'm sure that you can achieve this better with Collection. The document is here. It provides you a more 'OO' way (similar to javascript) you can operate arrays in php.
For an indexed array,
function diff($arr1, $arr2){
$arr3=array();
for($i=0;$i<count($arr1);$i++){
$arr3[$i]=$arr1[$i]-$arr2[$i];
}
print_r($arr3);
}
$arr1=array(300,300,300);
$arr2=array(100,100,100);
diff($arr1, $arr2);
//Displays 200, 200, 200, as expected
I have an array like this
array={'a'=>'2','b'=>'5', 'c'=>'6', 'd'=>'6', 'e'=>'2'};
The array value might be different depending on the $_POST variables. My question is how to find the highest value in my array and return the index key. In my case, I need to get 'c' and 'd' and the value of 6. Not sure how to do this. Any helps would be appreciated. Thanks.
$max = max(array_values($array));
$keys = array_keys($array, $max);
Have a look at arsort which will sort an array in reverse order and maintain index association. So:
arsort($array);
This will end up with the largest values at the top of the array. Depending on what you need array_unique can remove duplicate values from your array.
$array = array(
'key1' => 22,
'key2' => 17,
'key3' => 19,
'key4' => 21,
'key5' => 24,
'key6' => 8,
);
function getHighest($array)
{
$highest = 0;
foreach($array as $index => $value)
{
if(is_numeric($value) && $value > $highest)
{
$highest = $index;
}
}
return $highest;
}
echo getHighest($array); //key5
Or this should do the magic, it would probably be faster than php built-in functions
$maxValue = -1;
$max = array();
foreach ($items as $key => $item) {
if ($item == $maxValue) {
$max[] = $key;
} elseif ($item > $maxValue) {
$max = array();
$max[] = $key;
$maxValue = $item;
}
}
I had some troubles implementing Lawler's algorithm but thanks to SO and a bounty of 200 reputation I finally managed to write a working implementation:
Lawler's Algorithm Implementation Assistance
I feel like I'm using too many variables and loops there though so I am trying to refactor the code. It should be simpler and shorter yet remain readable.
Does it make sense to make a class for this? Any advice or even help with refactoring this piece of code is welcomed:
<?php
/*
* #name Lawler's algorithm PHP implementation
* #desc This algorithm calculates an optimal schedule of jobs to be
* processed on a single machine (in reversed order) while taking
* into consideration any precedence constraints.
* #author Richard Knop
*
*/
$jobs = array(1 => array('processingTime' => 2,
'dueDate' => 3),
2 => array('processingTime' => 3,
'dueDate' => 15),
3 => array('processingTime' => 4,
'dueDate' => 9),
4 => array('processingTime' => 3,
'dueDate' => 16),
5 => array('processingTime' => 5,
'dueDate' => 12),
6 => array('processingTime' => 7,
'dueDate' => 20),
7 => array('processingTime' => 5,
'dueDate' => 27),
8 => array('processingTime' => 6,
'dueDate' => 40),
9 => array('processingTime' => 3,
'dueDate' => 10));
// precedence constrainst, i.e job 2 must be completed before job 5 etc
$successors = array(2=>5,
7=>9);
$n = count($jobs);
$optimalSchedule = array();
for ($i = $n; $i >= 1; $i--) {
// jobs not required to precede any other job
$arr = array();
foreach ($jobs as $k => $v) {
if (false === array_key_exists($k, $successors)) {
$arr[] = $k;
}
}
// calculate total processing time
$totalProcessingTime = 0;
foreach ($jobs as $k => $v) {
if (true === array_key_exists($k, $arr)) {
$totalProcessingTime += $v['processingTime'];
}
}
// find the job that will go to the end of the optimal schedule array
$min = null;
$x = 0;
$lastKey = null;
foreach($arr as $k) {
$x = $totalProcessingTime - $jobs[$k]['dueDate'];
if (null === $min || $x < $min) {
$min = $x;
$lastKey = $k;
}
}
// add the job to the optimal schedule array
$optimalSchedule[$lastKey] = $jobs[$lastKey];
// remove job from the jobs array
unset($jobs[$lastKey]);
// remove precedence constraint from the successors array if needed
if (true === in_array($lastKey, $successors)) {
foreach ($successors as $k => $v) {
if ($lastKey === $v) {
unset($successors[$k]);
}
}
}
}
// reverse the optimal schedule array and preserve keys
$optimalSchedule = array_reverse($optimalSchedule, true);
// add tardiness to the array
$i = 0;
foreach ($optimalSchedule as $k => $v) {
$optimalSchedule[$k]['tardiness'] = 0;
$j = 0;
foreach ($optimalSchedule as $k2 => $v2) {
if ($j <= $i) {
$optimalSchedule[$k]['tardiness'] += $v2['processingTime'];
}
$j++;
}
$i++;
}
echo '<pre>';
print_r($optimalSchedule);
echo '</pre>';
I would make it a class. I find it easier to refactor an algorithm when all necessary variables are encapsulated as class members, rather than remembering what values I have to pass in and out every time I extract a method.
You should set your inputs to the algorithm in the constructor and then have a generic execute method. This would allow you to conform to both the command and strategy patterns more easily.
Make all your loop and conditional bodies into individual protected functions. With appropriate naming, that will increase the readability immensely, and make it much easier to alter the algorithm through inheritance.