array_splice() isn't working properly inside a loop - php

This code works as expected and removes the array element when the value is either 5 or 10. But it only works when I have 1 value which is 5 or 10 in the array.
If I have more than 1 value which is 5 or 10 it removes only 1 of them and leaves the other elements in the array.
My code:
for($i = 0; $i <= 10; $i++) {
if($somevar[$i] == 5 || $somevar[$i] == 10) {
echo 'the sumvar'.$somevar[$i].' exists<br>';
array_splice($somevar, $i, 1);
}
}
As an example if I have: [3, 5, 4] the result is as expected: [3, 4]. But if I have an array like: [3, 5, 10, 4] it just removes the 5, but not the 10: [3, 10, 4].
I can't seem to find it what I'm doing wrong and why my code doesn't work as expected?

You seem to miss that the array-elements are renumbered after the splice-operation.
You would have to adjust the loop-variable:
for($i = 0; $i < sizeof($somevar); $i++) {
if($somevar[$i] == 5 || $somevar[$i] == 10) {
echo 'the sumvar'.$somevar[$i].' exists<br>';
array_splice($somevar, $i, 1);
<b>$i--;</b>
}
}

Related

How to efficiently sum paired array elements and avoid offset errors in case of pairless array?

Pair every two arrays is the task – store it, print it and repeat it until it becomes one value.
input : 1, 2, 3, 4, 5, 6, 8, 9, 9
output: 3 7 11 17 9
10 28 9
38 9
47
My code is working fine in this scenario. Somehow I managed to add 0 at the end for pairless elements. But my main focus is how can I make the logic even more clearer to avoid grumpy offset errors?.
My code:
function sumForTwos($arr)
{
if(count($arr) == 1){
exit;
}
else {
$sum = [];
for ($i = 0; $i < count($arr) -1; $i++)
{
//logic to add last array for odd count to avoid offset error
if(count($arr) % 2 == 1){ $arr[count($arr)] = 0; }
//logic to pair arrays
if($i != 0) { $i++; }
$sum = $arr[$i] + $arr[$i + 1];
$total[] = $sum;
echo $sum . " ";
}
echo "<br>";
$arr = $total;
//Recursion function
sumForTwos($arr);
}
}
sumForTwos([1, 2, 3, 4, 5, 6, 8, 9, 9]);
You can adopt an iterative approach and look at this as processing each level of values with every next level have 1 value less from total values. In other words, you can look at this as a breadth first search going level by level. Hence, you can use a queue data structure processing each level one at a time.
You can use PHP's SplQueue class to implement this. Note that we can advantage of this class as it acts as a double-ended queue with the help of below 4 operations:
enqueue - Enqueues value at the end of the queue.
dequeue - Dequeues value from the top of the queue.
push - Pushes value at the end of the doubly linked list(here, queue is implemented as doubly linked list).
pop - Pops a node from the end of the doubly linked list.
Most certainly, all the above 4 operations can be done in O(1) time.
Algorithm:
Add all array elements to queue.
We will loop till the queue size is greater than 1.
Now, if queue level size is odd, pop the last one and keep it in buffer(in a variable).
Add all pairwise elements by dequeueing 2 at a time and enqueue their addition for next level.
After level iteration, add the last element back if the previous level size was odd.
Print those added elements and echo new lines for each level accordingly.
Snippet:
<?php
function sumForTwos($arr){
if(count($arr) == 1){
echo $arr[0];
return;
}
$queue = new SplQueue();
foreach($arr as $val){
$queue->enqueue($val); // add elements to queue
}
while($queue->count() > 1){
$size = $queue->count();
$last = false;
if($size % 2 == 1){
$last = $queue->pop(); // pop the last odd element from the queue to make queue size even
$size--;
}
for($i = 0; $i < $size; $i += 2){
$first = $queue->dequeue();
$second = $queue->dequeue();
echo $first + $second," ";
$queue->enqueue($first + $second);
}
if($last !== false){// again add the last odd one out element if it exists
echo $last; // echo it too
$queue->push($last);
}
echo PHP_EOL;// new line
}
}
sumForTwos([1, 2, 3, 4, 5, 6, 8, 9, 9]);
Demo: http://sandbox.onlinephpfunctions.com/code/5b9f6d4c9291693ac7cf204af42d1f0ed852bdf9
Does this do what you want?
function pairBySums($inputArray)
{
if (sizeof($inputArray) % 2 == 1) {
$lastEntry = array_pop($inputArray); //$inputArray now has even number of elements
}
$answer = [];
for ($ii = 0; $ii < sizeof($inputArray) / 2; $ii++) {
$firstIndexOfPair = $ii * 2; // 0 maps to 0, 1 maps to 2, 3 maps to 4 etc
$secondIndexOfPair = $firstIndexOfPair + 1; // 0 maps to 1, 1 maps to 3, 2 maps to 5 etc
$answer[$ii] = $inputArray[$firstIndexOfPair] + $inputArray[$secondIndexOfPair];
}
if (isset($lastEntry)) {
array_push($answer, $lastEntry);
}
echo implode(' ', $answer) . "<br>";
if (sizeof($answer) > 1) {
pairBySums($answer);
}
}
The algorithm makes sure it operates on an even array and then appends the odd entry back on the array if there is one.
$input = [1, 2, 3, 4, 5, 6, 8, 9, 9];
pairBySums($input);
produces:
3 7 11 17 9
10 28 9
38 9
47
With an even number of items,
$input = [1, 2, 3, 4, 5, 6, 8, 9];
pairBySums($input);
produces:
3 7 11 17
10 28
38

I want to get elements from array in order: three, four, three, four and so on

I want to get elements from an array like this: get first three element, then four elements, then again three elements, and again four, and so on in a loop.
For example:
0 1 2
3 4 5 6
7 8 9
10 11 12 13
and so on....
I tried something like this:
foreach($items as $key => $item) {
if($key <= 2) {
echo 'test';
}
if($key > 2 && $key < 6) {
echo 'other test';
}
if($key > 6 && $key < 9) {
echo 'test';
}
}
However, I don't want to use if() like these, because I don't know how many items will be in the array: it comes from a database.
I think, I need something like array_chunk($items, 3) but for size parameter I need 3 and 4 in loop
Could be like this you can make another array of specifying the number of elements you want in each iteration.
<?php
$number_of_elements = [3,4,3,4];
$your_array = ['a', 'b','c','d','e'];
foreach($number_of_elements as $number){
for($i = 0; $i<=$number; $i++){
$result = $your_array[$i];
print_r($result);
}
print_r('<br>');
}
In JavaScript you can solve your problem using a for loop and the built in slice function of the array.
const array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
let offset = 0;
for(let i = 0; i < array.length;){
offset = offset === 3 ? 4 : 3;
const subArray = array.slice(i, i + offset);
console.log(subArray);
i += offset;
}

PHP array slice from position + attempt to return fixed number of items

I'm looking for an efficient function to achieve the following. Let's say we have an array:
$a = [0, 1, 2, 3, 4, 5, 6, 7];
Slicing from a position should always return 5 values. 2 before the position index and 2 values after the position index - and of course, the position index itself.
If a position index is at the beginning of the array i.e. 0 (example 2), the function should return the next 4 values. Similarly, if the position index is at the end of the array (example 3), the function should return the previous 4 values.
Here's some examples of various indexes one could pass to the function and expected results:
$index = 3; // Result: 1, 2, 3, 4, 5. *example 1
$index = 0; // Result: 0, 1, 2, 3, 4. *example 2
$index = 7; // Result: 3, 4, 5, 6, 7. *example 3
$index = 6; // Result: 3, 4, 5, 6, 7. *example 4
As represented in examples: (example 1, example 4), the function should always attempt to catch tokens succeeding and preceding the position index - where it can, whilst always returning a total of 5 values.
The function must be bulletproof to smaller arrays: i.e if $a has 4 values, instead of 5, the function should just return everything.
Something like this?
#edit:
Sorry, I misread your original requirement. Second attempt:
function get_slice_of_5($index, $a) {
if ($index+2 >= count($a)) {
return array_slice($a, -5, 5)
}
else if($index-2 <= 0) {
return array_slice($a, 0, 5)
}
else return array_slice($a, $index-2, 5)
}
Create a start position by calculating where to start and use implode and array slice to return the string.
$a = [0, 1, 2, 3, 4, 5, 6, 7];
$index = 3; // Result: 1, 2, 3, 4, 5. *example 1
echo pages($a, $index) . "\n";
function pages($a, $index){
if($index >= count($a)-2){
$start = count($a)-5; // index is at end of array
}elseif($index <=2){
$start = 0; // index is at start
}else{
$start = $index-2; // index is somewhere in the middle
}
return implode(", ", array_slice($a, $start, 5));
}
https://3v4l.org/aNZsB
this is a "standalone" function to get spliced arrays of any size:
$a = [1,2,3,4,5,6,7,8,9];
echo "<pre>"; print_r(array_slicer($a, 2));
function array_slicer($arr, $start){
// initializations
$arr_len = count($arr);
$min_arr_len = 5; // the size of the spliced array
$previous_elements = 2; // number of elements to be selected before the $start
$next_elements = 2; // number of elements to be selected after the $start
$result = [];
// if the $start index doesn't exist in the given array, return false!
if($start<0 || $start>=$arr_len){
return false;
} elseif($arr_len <= $min_arr_len){ // if the size of the given array is less than the d size of the spliced array, return the whole array!
return $arr;
}
// check if the $start has less than ($previous_elements) before it
if($arr_len - ($arr_len - $start) < $previous_elements){
$next_elements += ($next_elements - ($arr_len - ($arr_len - $start)));
} elseif(($arr_len - 1 - $start) < $next_elements){ // check if the $start has less than ($next_elements) after it
$previous_elements += ($previous_elements - ($arr_len - 1 - $start));
}
for($i = ($start-$previous_elements); $i <= ($start + $next_elements); $i++){
if($i>-1 && $i<$arr_len){
$result[] = $arr[$i];
}
}
return $result;
}
You can define the bounds of where the array_slice() will begin by leveraging min() and max(). Assuming your array will always have at least 5 element, you can use:
array_slice($a, min(count($a) - 5, max(0, $index - 2)), 5)
The chosen index will be in the center of the sliced array unless it cannot be.
Dynamic Code: (Demo)
$a = [0, 1, 2, 3, 4, 5, 6, 7];
$count = count($a);
$span = 5; // most sensible with odd numbers
$center = (int)($span / 2);
foreach ($a as $i => $v) {
printf(
"%d: %s\n",
$i,
implode(
',',
array_slice(
$a,
min($count - $span, max(0, $i - $center)),
$span
)
)
);
}
Output:
0: 0,1,2,3,4
1: 0,1,2,3,4
2: 0,1,2,3,4
3: 1,2,3,4,5
4: 2,3,4,5,6
5: 3,4,5,6,7
6: 3,4,5,6,7
7: 3,4,5,6,7

How can I find how often the sum of three consecutive values in a set equal a certain value?

9 numbers. Count how often the sum of 3 consecutive numbers in this set of numbers equaled to 16:
2, 7, 7, 1, 8, 2, 7, 8, 7,
The answer is 2. 2 + 7 + 7 = 16 and 7 + 1 + 8 = 16
But I can't seem to get the answer, because I don't know how to "loop" back and skip the first number and do the process over.
How would one be able to solve this utilizing arrays, and how would one solve this without utilizing arrays?
The 9 numbers are randomly generated, and it has to stay that way, but for the sake of solving, I used seed of 3 using srand(3). This is my current code below:
<?php
srand(3);
$count = 1;
$answer = 0;
$num1 = 0;
$num2 = 0;
$num3 = 0;
for ($i = 0; $i < 9; $i++)
{
$num = rand(0, 9);
echo $num . ', ';
if ($count == 1)
$num1 = $num;
else if ($count == 2)
$num2 = $num;
else if ($count == 3)
{
$num3 = $num;
$count = 1;
}
if ($num1 + $num2 + $num3 == 16)
$answer++;
$count++;
}
echo '<br />*******' . $answer . '*******';
?>
Obviously this isn't the right answer because I had to do the check again, but skipping the first number, and so on and so forth until (the last indexed number - index 3)
Probably not the most efficient solution, but its hard to think at 11 at night:
$array = array(2, 7, 7, 1, 8, 2, 7, 8, 7);
$count = count($array);
for ($x = 0; $x < $count; $x++) {
$parts = array_chunk($array, 3);
foreach ($parts as $part) {
if (array_sum($part) == 16 && count($part) == 3) {
print_r($part);
}
}
array_shift($array);
}
Another solution which I think is the more efficient, logic similar to what #Jeroen Vannevel answered:
$array = array(2, 7, 7, 1, 8, 2, 7, 8, 7);
$count = count($array) - 2;
for ($x = 0; $x < $count; $x++) {
if ($array[$x] + $array[$x+1] + $array[$x+2] == 16) {
echo "{$array[$x]} + {$array[$x+1]} + {$array[$x+2]} = 16 <br />";
}
}
Not a PHP writer but this could be your approach:
Fill the array from indices 0 up to and including 8 with a random value.
Iterate from index 0 to index [length - 3]. (length is 9)
Calculate the sum of the values on index [currentIndex], [currentIndex + 1] and [currentIndex + 2].
Whenever the value of that sum equals 16, increment your [count] variable by 1.

Default php function that turns negative numbers in 0

Is there such a thing?
for eg
$var = -5;
echo thefunction($var); // should be 0
$var = 5;
echo thefunction($var); // should be 5
Try max($var,0), which will have the desired effect. See the manual page for more information.
Not built-in but, here you have:
function thefunction($var){
return ($var < 0 ? 0 : $var);
}
Hope this helps
In PHP, checking if a integer is negative and if it is then setting it to zero is easy, but I was looking for something shorter (and potentially faster) than:
if ($x < 0) $x = 0;
Well, this is a very quick check and reset, but there is a function max that does this too and it works with arrays too.
$x = max(0, $x); // $x will be set to 0 if it was less than 0
The max() function returns the number with the highest value of two specified numbers.
echo max(1, 3, 5, 6, 7); // 7
echo max(array(2, 4, 5)); // 5
echo max(0, 'hello'); // 0
echo max('hello', 0); // hello
echo max(-1, 'hello'); // hello
// With multiple arrays, max compares from left to right
// so in our example: 2 == 2, but 4 < 5
$val = max(array(2, 4, 8), array(2, 5, 7)); // array(2, 5, 7)
// If both an array and non-array are given, the array
// is always returned as it's seen as the largest
$val = max('string', array(2, 5, 7), 42); // array(2, 5, 7)
function thefunction($number){
if ($number < 0)
return 0;
return $number;
}
that should do the trick
Simply:
echo $var < 0 ? 0 : $var;

Categories