1

Need subarray difference of below array

$arr = array(
    array('s'=>'1','e'=>'3'),
    array('s'=>'6','e'=>'7'),
    array('s'=>'8','e'=>'9'),
    array('s'=>'10','e'=>'14'),
    array('s'=>'16','e'=>'17'),
)

if(arr[$arr[$i+1][s] - $i][e] <= 1){
//join them
}
else {
//save them as it is
}

Desired result should

$arr = array(
    array('s'=>'1','e'=>'3'),
    array('s'=>'6','e'=>'14'),
    array('s'=>'16','e'=>'17'),
)

No consecutive (next S-E) should be 1

http://codepad.org/V8omMdn6 is where im struck at

See its like

iteration 0
6-3 = 3 
so save array('s'=>'1','e'=>'3'),

    iteration 1
    8-7 = 1
    array('s'=>'6','e'=>'9'), => discade in 2 as it

    iteration 2
    10-9 = 1
    array('s'=>'6','e'=>'10'), => discade in 3 as it

iteration 3
10-9 = 1
array('s'=>'6','e'=>'14'),

iteration 4
16-14 = 4
array('s'=>'16','e'=>'17'),
13
  • Could you elaborate what you mean by //join them Commented Jun 16, 2016 at 10:42
  • join as in make s of $i index and e of $i+1 index check my result arr Commented Jun 16, 2016 at 10:45
  • I'm struggling to figure out what you want from your desired result compared to the original array. What do you mean by "No consecutive (E-S) should be 1" especially as your comparison is doing s - e not e - s. Commented Jun 16, 2016 at 10:47
  • No consecutive (E-S) should be 1 mean ($i+1)E - ($i)S if = 1 than join them, neither save them as it is. Commented Jun 16, 2016 at 10:53
  • @AnitaMourya Well that is completely different from what your code says. A basic requirement of getting an answer is making sure your question is accurate. Your code basically says ($i + 1)S - ($i)E < 1. Commented Jun 16, 2016 at 10:54

3 Answers 3

1
$result = [];

foreach ($arr as $pair) {
    if (empty($result) || $pair['s'] - end($result)['e'] > 1) {
        $result[] = $pair;
    } else {
        $result[key($result)]['e'] = $pair['e'];
    }
}

You might also use $last as key instead end() & key() for readability. Using array pointer functions on $result shortens the code but uses some ugly hidden effects. end($result) returns last element of array (using key bracket with function result is possible since php5.3 I guess), but also sets the pointer, so key($result) will return correct key if needed.

While iterating you process last element of result array - this element might not be valid right away, but you don't need to look ahead. There are two scenarios for last element (+initial state condition for empty $result):

  • invalid: set e value from current item and process further
  • valid: leave it and push current item into results for further validation (unless that was the last one).
Sign up to request clarification or add additional context in comments.

Comments

0

I took a very brief look at your codepen, I think what you want to achieve is to find out if the start time of a new session is within a given period from the end time of the last session, if so you would like to combine those sessions. I think you confused yourself by trying to subtract start time of new session from end time of last session, it should be the other way round.
The way you worded the question made it even more confusing for people to understand.
If my interpretation of your question is correct, the below code should work with the test case you posted here.

function combineSession($arr){
$arrCount=count($arr)-1;

for ($i=0; $i<$arrCount; $i++){
//if the difference between s and e is less than or equal to one, then there is a consecutive series
    if($arr[$i+1]['s']-$arr[$i]['e'] <= 1){
//assign the value of s at the start of a consecutive series to $temp
        if (!isset($temp)){
            $temp=$arr[$i]['s'];
        }
//if consecutive series ends on the last sub_array, write $temp e pair to output
        if ($i==$arrCount-1){
            $output[]= array('s'=> $temp, 'e' => $arr[$arrCount]['e']); 
        }
    }
//end of a consecutive series, write $temp and e pair to output, unset $temp
    else if (isset($temp) && $i<$arrCount-1){
        $output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
        unset($temp);
    }
//consecutive series ended at the second last sub-array, write $temp and e pair to output and copy key value pair of the last sub-array to output
    else if ($i==$arrCount-1){
        $output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
        $output[]=$arr[$arrCount]; 
    }
//not in a consecutive series, simply copy s e key value pair to output
    else {
        $output[]=$arr[$i]; 
    }
}//end of for loop
print_r($output); 
}//end of function

8 Comments

@AnitaMourya you should use shudder's solution instead, way cleaner than what I posted and the second approach I proposed
no his solution doesn't give me the required result, can you do most of the things inside the function instead of outside?
his solution does what you asked for but in a much smarter way, perhaps you didn't follow the logic or test it right? As for doing most things inside the function, you can move the if else statement of $result into the function by replacing the return statement with a $output[]= but you would need to add another else if statement for cases where s doesn't discade into the last element.
@AnitaMourya I edited the code to move everything to the function, but as mentioned the other answer offers a smarter solution.
temp is not set at else if ($i==$arrCount-1){ $output[]=array('s'=> $temp, 'e' => $arr[$i]['e']);
|
0

else if ($i==$arrCount-1){ $output[]=!isset($temp) ? $arr[$i] : array('s'=> $temp, 'e' => $arr[$i]['e']); $output[]=$arr[$arrCount]; }

1 Comment

Sorry this is meant to be a comment. I can't seem to delete this wrong entry using the app. Will remove this when I get to my computer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.