I have this array.
$val = array(12:10, 4:16, 2:05);
I want to subtract 14:00 hrs from the $val array in the way that from every element that element do not become negative like this:
$val = array(0, 2:26, 2:05)
<?php
$input = "14:00";
$val = array("12:10", "4:16", "2:05");
function timeSubtractionFirstTime($actual_time ,$time_to_reduce){
$actual_time_array = explode(":",$actual_time);
$time_to_reduce = explode(":",$time_to_reduce);
$final_result = [];
if($actual_time_array[1] < $time_to_reduce[1]){
$actual_time_array[0] = $actual_time_array[0]-1;
$final_result[] = $actual_time_array[1]+60-$time_to_reduce[1];
}else{
$final_result[] = $actual_time_array[1]-$time_to_reduce[1];
}
$final_result[] = $actual_time_array[0]-$time_to_reduce[0];
return implode(":", array_reverse($final_result));
}
$timeToReduceLeft = $input;
foreach ($val as &$value) {
$diff = timeSubtractionFirstTime($value, $timeToReduceLeft);
if (strpos($diff, chr(45)) !== false){ //if $value < $timeToReduceLeft
$timeToReduceLeft = timeSubtractionFirstTime($timeToReduceLeft, $value);
$value = "00:00";
}
else { //if $value >= $timeToReduceLeft
$value = timeSubtractionFirstTime($value, $timeToReduceLeft);
$timeToReduceLeft = "00:00";
}
if ($timeToReduceLeft == "00:00"){
break;
}
}
echo implode(",", $val);
I get the function to extract time from this post and implement the logic for your problem as follows:
We substract the time from input value until the input value become zero or entire array elements become zero (by forloop).
This solution also works with input or array elements value greater than "24:00".
Related
I need to find the min and max position into an array where some value exist!
use a loop inside a loop to compare values is not an option ( my array has 100.000 values )
e.g=
$myarray[0]="red";
$myarray[1]="red";
$myarray[2]="blue";
$myarray[3]="blue";
$myarray[4]="blue";
$myarray[5]="red";
how to get the min and max position where blue exist?
Use the second argument for array_keys:
if($blue = array_keys($myarray, 'blue')) {
$min = min($blue);
$max = max($blue);
}
may be this is the answer?
function getMinKey($arr, $search){
if(!in_array($search, $arr)){
return false;
}
foreach($arr as $key => $value){
if($value == $search){
return $key;
}
}
}
function getMaxKey($arr, $search){
if(!in_array($search, $arr)){
return false;
}
$arrCount = count($arr)-1;
for($i = $arrCount; $i >=0; $i--){
if($arr[$i] == $search){
return $i;
}
}
}
All solutions, so far, have searched the whole array, which might be quite inefficient. You only need to search from the start upto the first "blue" and from the end downto the last "blue". Like this:
$find = "blue";
$first = false;
$last = false;
$max = count($myarray);
$key = 0;
while ($key < $max) {
if ($myarray[$key] == $find) {
$first = $key;
break;
}
$key++;
}
if ($first !== false) {
$key = --$max;
while ($key > 0) {
if ($myarray[$key] == $find) {
$last = $key;
break;
}
$key--;
}
}
Note that this code takes into account that nothing will be found. In that case $first and $last will contain false. It also checks to see if the $first was found to prevent searching through the array twice when there's clearly no need for that.
You can use array_keys with the search_value to extract all the matching keys, and then max and min to get the two ones that you want.
$keys = array_keys($myarray,'blue'); //[2,3,4]
$maxKey = max($keys); //4
$minKey = min($keys); //2
I have to advise that performance wise is better to do a for loop:
$length = count($myarray);
$minKey = FALSE;
$maxKey = FALSE;
$search = 'blue';
for($i=0;$i<$length;$i++){
if($myarray[$i] == $search){
if($minKey === FALSE) $minKey = $i;
$maxKey = $i;
}
}
This question already has answers here:
How to find first array element with value greater than X in PHP?
(2 answers)
Closed 1 year ago.
Say, there is an array and a number:
$values = ['a'=>10, 'b'=>20, 'c'=>30];
$num = 25;
How can I find an index of the array element the value of which is less than the number?
In the above example it will be the 'b' index of which is 1.
You could sort the array by the values then loop through it until a number is hit above the $num. Here is a quick example:
$values = ['a'=>10, 'b'=>20, 'c'=>30];
$num = 25;
$sortedValues = $values;
asort($sortedValues);
while (($current = current($sortedValues)) !== false && $current < $num) {
$lastValue = key($sortedValues);
next($sortedValues);
}
echo $lastValue;
I got it:
$values = ['a'=>1, 'b'=>20, 'c'=>30, 'd'=>40, 'e'=>50];
$num = 55;
$i = null;
foreach ($values as $k => $v){
if ($v == $num){
echo $v;
break;
}
elseif ($num >= 1 && $v > $num){
echo $values[$i];
break;
}
elseif ($num > end($values)){
echo end($values);
break;
}
$i = $k;
}
May be array_filter can be some more handy:
$values = ['a'=>1, 'b'=>20, 'c'=>30, 'd'=>40, 'e'=>50];
$num = 45;
// filter items less than $num
$lesser = array_filter($values, function($v) use($num) {
return $v < $num;
});
// get necessary item/index from filtered, last for example
$lesserKeys = array_keys($lesser);
$lastOfLessKey = end($lesserKeys);
$lastOfLess = end($lesser);
var_dump($lastOfLessKey, $lastOfLess); // d 40
$values = ['a'=>10, 'b'=>20, 'c'=>30];
$num = 25;
foreach($value as $key => $val){
if( (int) $val == (int) $num){
echo 'this is what you are searching. key is: '.$key.', value is: '.$val;
}
}
I have range array in PHP which contain no of range, but i want to marge that all possible rang by around near value ..!
Range array like this :
$array = array('1.10','21.30','31.40','41.50','81.90');
And i want like below after marge :
$array = array('1.10','21.50','81.90');
I tried to merged, but I wanted to find out the result that I did not have.
$dis = array();
$array = array('1.10','21.30','31.40','41.50','81.90');
foreach ($array as $value) {
$ex = explode('.',$value);
if(isset($dis[$ex[1] + 1])){
$dis[$ex[1] + 1][0] = $ex[0];
}else if(isset($dis[$ex[0] - 10])){
$dis[$ex[0] - 10][1] = $ex[1];
}else $dis[$ex[0]] = $ex;
}
$new_array = array();
foreach($dis as $value){
$new_array[] = implode('.',$value)
}
//Output : array('1.10','21.50','41.50','81.90')
Will there be any easy solution for this ?
Yuu... Finally i made this ans and it working fine..!
$dis = array();
$array = array('121.130','101.110','31.40','61.70','1.10','21.30','51.60','81.90','111.120');
sort($array);
foreach($array as $value){
$ex = explode('.',$value);
$no = $ex[0] - 1;
if(isset($dis[$no])){
$dis[$ex[1]] = array($dis[$no][0],$ex[1]);
unset($dis[$no]);
}else $dis[$ex[1]] = $ex;
}
$new_array = array_map(function($v){ return implode('.',$v); }, $dis);
i have array:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 7 )
how to make condition in php when looping i can get output:
$datarange = 1-3,7;
i got logic like this:
if (value of array[0] + 1) = value of array[1] {
$datarange = value of array[0] - value of array[1];
}else{
$datarange = value of array[0] , value of array[1];
}
but i dont know how to Implement that to my looping
Here's a function that will make ranges when possible in an array of numbers.
<?php
function getRange($numbers) {
$lastNumber = null;
$currentRange = [];
$ranges = [];
foreach ($numbers as $number) {
if ($lastNumber === null) { // first iteration, add the number to current range
$currentRange[] = $number;
}
else {
if ($number - $lastNumber === 1) { // if difference with last number is 1, they're consecutive
$currentRange[] = $number;
}
else { // they're not consecutive, finish current range and start a new one
$ranges[] = $currentRange;
$currentRange = [$number];
}
}
$lastNumber = $number; // set the last number to compare with the next
}
$ranges[] = $currentRange; // add last range
$rangesString = []; //
foreach ($ranges as $range) {
$str = $range[0];
if (count($range) > 1) {
$str .= "-".$range[count($range) - 1];
}
$rangesString[] = $str;
}
return implode(", ", $rangesString);
}
echo getRange([1,2,3,7]); // result = 1-3, 7
echo getRange([1,2,6,9,10,12,15,17,18,19]); // result = 1-2, 6, 9-10, 12, 15, 17-19
Try this. I have change your logic and apply it in loop. for range:
$arr = array(1,2,3,7);
$last_val = "";
$first_val = "";
$add_val = true;
foreach ($arr as $key => $value) {
if($first_val == "")
$first_val = $value;
if(isset($arr[$key+1]))
{
if($value+1 == $arr[$key+1])
{
$last_val = $arr[$key+1];
$add_val = false;
}
else
$add_val = true;
}
else
$add_val = true;
if($add_val)
{
if($last_val != "")
$datarange[] = $first_val."-".$last_val;
else
$datarange[] = $first_val;
$first_val = "";
$last_val = "";
}
}
echo implode(",", $datarange);
DEMO
I need to find not just duplicates in an array, but numbers that are within 1 of each other.
example: $myArr = array(46,78,77,43,86,1,47,14,51,31)
How would I get find those numbers if there no duplicates were found?
Thanks.
This will work - tested:
$myArr = array(46,78,77,43,86,1,47,14,51,31);
$i = 1;
while($i <= 99){
if(in_array($i, $myArr)){
// This means it's in the array
// Let's see if it's +1 of the last #
if(isset($last_num)){
$res = ($i + 1);
if(in_array($res, $myArr)){
echo $res . ' is in the array<br>';
}
}
}
$last_num = $i;
$i++;
}
Could use something like this.
<?
$haystack = array(31,46,78,77,43,86,1,47,14,51,31);
array_walk($haystack, function($key, $value) use ($haystack) {
$needle = array($key - 1, $key, $key + 1);
$r = array_intersect($haystack, $needle);
if(count($r) > 1) { unset($r[$value]); print_r(array_values($r)); }
});
?>
Or if you want them returned in an array:
<?
$haystack = array(31,46,78,77,43,86,1,47,14,51,31);
$result = array_filter(array_map(function($key, $value) use ($haystack) {
$needle = array($key - 1, $key, $key + 1);
$r = array_intersect($haystack, $needle);
if(count($r) > 1) { unset($r[$value]); return array_values($r)['0']; }
}, $haystack));
print_r($result);
?>
A little more verbose, but it may be more efficient since we're only looping through the array when necessary. It will return the keys of the original array where duplicates and values within range are found. (Note: I've expanded the code out a lot more than I normally would just for readability for OP)
/**
* Find the any values within an array that are within
* the specified range from another value.
*
* #param Array Array to search in
* #param uint Unsigned integer used for comparison
* #return Array The keys of all found values
**/
function findWithinRange(Array $array, $range) {
// sort the array values numerically
// so we don't have to loop through
// the entire array for each check
asort($array, SORT_NUMERIC);
// Keep the keys in case it's an associative array
$keys = array_keys($array);
// Get the values without the keys so we can easily loop
$values = array_values($array);
$return = array();
// Loop over each item in the array
foreach( $values as $k => $v ) {
$start = $k;
$min = $v - $range;
$max = $v + $range;
// track backwards in the array until we're less than range
// We could use array_search, but we'd be calling it multiple times
// This only runs through the array once and dies the moment
// it is out of the specified range
while(true) {
$k--;
if( !isset($values[$k]) ) {
break; // don't continue if we run out of keys
}
$curVal = $values[$k];
if( $curVal >= $min ) {
$return[] = $keys[$k];
}
else {
break; // kill the while loop if we're outside of range
}
}
// reset
$k = $start;
// track forward in the array until we're greater than range
while(true) {
$k++;
if( !isset($values[$k]) ) {
break; // don't continue if we run out of keys
}
$curVal = $values[$k];
if( $curVal <= $max ) {
$return[] = $keys[$k];
}
else {
break; // kill the while loop if we're outside of range
}
}
}
// drop duplicate reports
$return = array_unique($return);
// return all found keys
return $return;
}
Example usage:
$myArr = array(46,78,77,43,86,1,47,14,51,31);
$res = findWithinRange($myArr, 1);
var_export($res);
// array(6, 0, 1, 2)