PHP array unset() behavior - last array key remains? - php

I have an array constructed out of several strings (HTTP addresses) on which I run a PHP Filter and the unset() method to remove non-valid URLs. However, the last array item is never removed - and I don't know why, or how I solve this. I'm hoping you guys can help.
$url1 = "http://localhost/work/project/scrapes/1.html";
$url2 = "";
$url3 = "";
$urls = array($url1, $url2, $url3);
for($x = 0; $x < sizeof($urls); $x++){
if(!filter_var($urls[$x], FILTER_VALIDATE_URL)){
unset($urls[$x]);
}
}
print_r() gives me this:
Array ( [0] => http://localhost/work/project/scrapes/1.html [2] => )
I have no idea why $urls[2] is still there, and why it's not removed.

Because you calculate the size() dynamically - it reduces as long as you delete elements. So the fix is to get the size before the loop:
$url1 = "http://localhost/work/project/scrapes/1.html";
$url2 = "";
$url3 = "";
$urls = array($url1, $url2, $url3);
$size = sizeof($urls); // <----
for($x = 0; $x < $size; $x++){
if(!filter_var($urls[$x], FILTER_VALIDATE_URL)){
unset($urls[$x]);
}
}
var_dump($urls);

That is because you are calculating the size of the array in each iteration.
By Iteration:
sizeof($urls) = 3, $x = 0, $x < sizeof($urls) TRUE unset($urls[0]);
sizeof($urls) = 2, $x = 1, $x < sizeof($urls) TRUE unset($urls[1]);
sizeof($urls) = 1, $x = 2, $x < sizeof($urls) FALSE ... no more code executed
save the length of the array before start the loop
$length = sizeof($urls);
for($x = 0; $x < $length; $x++){
}

Related

PHP - get random integer using random_int() without repeating and looping

I need to get 50 random numbers out of range 1-100 without repeating. The current way i do is :
$array = array();
while (count($array) <= 50) {
$temp = random_int(1,100);
if (!in_array($temp, $array))
$array[] = $temp;
}
However, the looping is too many because I need to generate for more than 100,000 times.
Is there other ways that I can get a 50 random non-repeating numbers without looping ?
For example:
$number= range(1,100);
$array = array_slice(shuffle($number),0,50);
I can't use shuffle because it uses pseudo random number.
Is there other ways to achieve what I need, or ways that could shorten time.
pre fill a array of numbers and pick from them, and then remove it.
it prevents the unnecessary random generations you have
$numbers = [];
for ($i = 1; $i <= 100; $i++) {
$numbers[] = $i;
}
$randomNumbers = [];
for ($i = 1; $i <= 50; $i++) {
$r = rand(0, count($numbers) - 1);
$randomNumbers[] = $numbers[$r];
array_splice($numbers, $r, 1);
}
This would be my approach:
This gives you 50 numbers in any case, and they are defenitely different from each other. PLUS: you dont have to prefill some other array:
$start = microtime(true);
for($i = 0; $i <= 100000; $i++){
$arr = [];
while(sizeof($arr) < 50){
$num = rand(1, 100);
$arr[$num] = $num;
}
if(array_unique($arr) !== $arr || sizeof($arr) !== 50 ){
print("FAIL");
}
//print(array_unique($arr) == $arr ? "true" : "false");print("<br>");
//print(sizeof($arr));print("<br>");
//print_r(array_count_values ($arr));print("<br>");
//print_r($arr);print("<br>");
}
$time_elapsed_secs = microtime(true) - $start;
print($time_elapsed_secs);print("<br>");
Running this 100000 times takes about 0.4sec for me.
The actual generation is done in this part:
$arr = [];
while(sizeof($arr) < 50){
$num = rand(1, 100);
$arr[$num] = $num;
}
We can do in 2 steps:
$x = 0;
$arr = [];
while($x < 50){
$tmp = rand(1, 100);
if(!in_array($tmp, $arr)){
$arr[] = $tmp;
$x++;
}
}

Populate 4 arrays evenly distributed as much as possible from top to bottom

This question is in relation to this post
How to distribute mysql result set in an multidimensional array of 4 arrays
I got the accepted answer but now i want to make a change to the code and i'm not having a lot of success...
Basically, from a mysql result set, i need to populate 4 arrays evenly distributed as much as possible from top to bottom...
Chris Hayes provided a solutuon that works, but when i tested it today, i realize that it populates the array from left to rigth, and not from top to bottom...
How do i change the code so it populates the 4 arrays as much as possible from top to bottom ?
$i = 0;
$array_r = array( array(), array(), array(), array() );
while ($stmt->fetch()) {
array_push($array_r[$i], array(... values ...));
$i = ($i + 1) % 4;
}
final version without manipulating the input array at all:
for ($num = count($input), $offset = 0; $numBuckets > 0; $numBuckets -= 1, $num -= $bucketSize, $offset += $bucketSize) {
$bucketSize = ceil($num / $numBuckets);
$output[] = array_slice($input, $offset, $bucketSize);
}
pervious answer:
Try the following:
<?php
$input = range('A', 'Z'); // test input data
$output = array(); // the output container
$numBuckets = 4; // number of buckets to fill
for (; $numBuckets > 0; $numBuckets -= 1) {
$output[] = array_splice($input, 0, ceil(count($input) / $numBuckets));
}
print_r($output);
alternative version, without constant rechecking the length of the array
for ($num = count($input); $numBuckets > 0; $numBuckets -= 1, $num -= $bucketSize) {
$bucketSize = ceil($num / $numBuckets);
$output[] = array_splice($input, 0, $bucketSize);
}
This snippet should work for you:
<?php
$array= [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
$strays = count($array)%4;
$offset = 0;
$results = array();
for($x = 0; $x < 4; $x++){
if ($x < $strays){
$size = (floor(count($array)/4) + 1);
} else {
$size = (floor(count($array)/4));
}
$results[] = array_slice($array, $offset, $size);
$offset+=$size;
}
print_r($results);
I've tested something and it seems to work... but it looks very spaghetti... please feel free to optimize the code. Thanks.
$num_rows = $stmt->num_rows; //number of records returned by the result set
$min_per_column = (int)($num_rows/4); //minimum records per column
$remainder = $num_rows % 4; //the remainder
$array_r = array(array(), array(), array(), array());
$i = 1;
$col = 0;
//how many records to populate before moving to the next array?
$rows = ($col < $remainder) ? $min_per_column + 1 : $min_per_column;
while ($stmt->fetch()) {
array_push($array_r[$col], array($r_recordingid, $r_title, $r_subtitle, $r_seourl));
$i++;
//initialize values for new array
if ($i > $rows) {
$i = 1;
$col++;
$rows = ($col < $remainder) ? $min_per_column + 1 : $min_per_column;
}
}

Invert matrix numbers - loop

First, i have these values.
$Arr1 = array(1/1, 1/2, 3/1);
$Arr2 = array(1/1, 4/1);
$Arr3 = array(1/1);
and i need an output with 3 arrays like these:
$a1 = array (1/1, 1/2, 3/1);
$a2 = array (2/1, 1/1, 4/1);
$a3 = array (1/3, 1/4, 1,1);
What i am trying is :
for ($i=0; $i<count($Arr1); $i++) {
${"a".$i} = array(
//here, the number of array elements depends to the length of $a1
);
}
Any help ? thanks
I think this image helps to understand the problem:
First off, using a 2D array will make your life a lot easier.
So first, initialize your values like this:
$matrix_size = 3;
$matrix = array();
for($i = 0; $i < $matrix_size; $i++){
$matrix[$i] = array_fill(0, $matrix_size, null);
}
$matrix[0][0] = 1/1;
$matrix[0][1] = 1/2;
$matrix[0][2] = 3/1;
$matrix[1][1] = 1/1;
$matrix[1][2] = 4/1;
$matrix[2][2] = 1/1;
Then you can run a loop like this:
foreach($x = 0; $x < $matrix_size; $x++){
foreach($y = 0; $y < $matrix_size; $y++){
if(is_null($matrix[y][x]) && !is_null($matrix[x][y])){
$matrix[y][x] = 1/$matrix[x][y];
}
}
}
I'm sure there is a much more efficient way to do this, but this is a start for you to explore.

Is there a way to walk dynamically into multidimensional arrays?

For example:
$size = 0;
$array = $array;
$size = 1;
$array = $array[x];
$size = 5;
$array = $array[x][x][x][x][x];
I got a $config array that can either have 1 dimension or many. Depending on setting of the var $size the elements I need walk gonna be on that position. If size = 1, I will be looking for $config[1]. If size = 2 I will be looking for $config[1][1] ...
Thanks,
$foo = $array;
for($i=0;$i<$size;++$i) {
$foo = $foo[x];
}
$array = $array[x][x][x][x][x];
for ($x = 0; $x < 5; $x++) {
if (!is_array($array[1])) break;
$array = $array[1];
}
You can make infinite loop and reach end of array.

2 One Dimensional arrays to 1 Two Dimensional array

I have two arrays like this
array x [Firefox,IE,Chrome,Opera]
array y [40,30,25,5]
Required final [[Firefox,40],[IE,30],[Chrome,25],[Opera,5]]
I need this in PHP.I think I can run a for loop and do something like this .
final23 [0][i] = x[i];
final23 [1][i] = y[i];
Is there any better way or built in function in PHP ?
$result = array();
$size = max(count($x), count($y));
for ($i = 0; $i < $size; $i++) {
$result[] = array(
isset($x[$i]) ? $x[$i] : null,
isset($y[$i]) ? $y[$i] : null
);
}
$x = array("Mozzila","IE","Firefox","Opera");
$y = array(40,30,25,5);
$final = array();
$i = 0;
foreach($x as $a){
$final[] = array($a,$y[$i]);
$i++;
}
Learn about Associated array.
$arr = new Array("40"=>"FireFox","30"=>"IE","25"=>"Chrome","5"=>"Opera");

Categories