empty array whenever it reaches a threshold - php

I've a loop that generates an array of all possible combinations of binary bits by giving the number of bits, but I got a memory issue when the number of its exceeds 20.
So I'm looking for a way to remove or empty the previous array values for example if the array reaches 1k or 2k values, here's the code :
for ($i = 1; $i <= ($listN - 1); $i++) {
$reverseBits = array_reverse($bits);
$prefixBit = preg_filter('/^/', '0', $bits);
$prefixReverseBits = preg_filter('/^/', '1', $reverseBits);
$bits = array_merge($prefixBit, $prefixReverseBits);
unset($prefixBit, $prefixReverseBits, $reverseBits);
}
I've tried this one but it does not work, the array will be fully empty outside the loop :
if(count($bits) > 1000){
unset($bits);
$bits = array();
}
Thank you for your help

Your code simply does nothing, if the $bits array is empty, because array_reverse and preg_filter do not modify the array size and array_merge only adds the existing numers together. So en empty array will always stay empty.
Instead set your "emtpy" array to the 1 bit default array ['0','1']:
if(count($bits) > 1000){
$bits = array('0','1');
}
In case you want to keep your "last 1000" results instead of deleting all reasults you got so far think about using $bits = array_slice($bits, 0, 1000); at the beginning of your loop.

For achieving something like that, you simply have to do something of the sort:
if(count($bits) > 1000){
$bits = array_slice($bits, 1000);
}
This will slice the array from the offset 1000 and leave the rest of the items of the array, intact.
Reference: http://php.net/manual/en/function.array-slice.php

Related

Find index if values in single array on either side are equal when summed

I have a whiteboard question that I think is way beyond my skill and so don't even know how to approach this.
I want to iterate through each value and sum the elements on left/right side and if they're equal return the index value.
So:
[1, 2, 3, 4, 3, 2, 1]; // return 3
The official question:
You are going to be given an array of integers. Your job is to take
that array and find an index N where the sum of the integers to the
left of N is equal to the sum of the integers to the right of N. If
there is no index that would make this happen, return -1.
Is anyone kind enough to help me out? I've looked at array_map() and array_filter() and while helpful I can't think of how to traverse back and forth between the current index when iterating the array.
This can be done with a simple for loop over the full range of an array combined with array_slice and array_sum.
function doSomething(array $data): int {
for ($i = 0, $count = count($data); $i < $count; $i++) {
$left = $i > 0 ? array_slice($data, 0, $i) : [ $data[0] ];
$right = $i > 0 ? array_slice($data, $i + 1) : $data;
$left_result = array_sum($left);
$right_result = array_sum($right);
if ($left_result === $right_result) {
return $i;
}
}
return -1;
}
This small piece of code loops over the whole array and sums up the left and the right of the current position of the array. The results will be compared and if the results are the same, the key of the array will be returned.
For huge arrays you can try to reduce memory consumption by using a yield or an Iterator instance.

Counting a number and push each number into an array

I am trying to figure out how to count a number that I pull from query string and push each into an array. so if the number is 3, I want to push 1, 2 and 3 as separate numbers into the array. The below code does not work:
$number = $_GET['tics'];
$items = array();
for($numbers = 0; $numbers<$number; $numbers++) {
$items[] = $numbers;
}
var_dump shows an empty array with this code. any idea how to make this work?
I want the key to be "numbers" and the values to be 1, 2, 3 etc..
I am sure this is explained many times already on stack, but when searching I found only examples that was way to advanced for someone like me
you can use range()
Returns an array of elements from start to end, inclusive.
$number = (int) $_GET['tics'];
$items = range(1, $number);
You can use http://php.net/manual/en/function.range.php to generate a list of numbers from min to max.
<?php
$number = 5;
// Do validation on $number before passing it to range.
$result = range(1, $number);
print_r($result);
For starters, your loop is incorrect.
If you pass $number = 3
for ($numbers = 0; $numbers < $number; $numbers++) {
Will give you 0, 1, 2. You need to change it to the following:
for ($numbers = 1; $numbers <= $number; $numbers++) {
This will give you 1, 2, 3.
Anyway, entertaining another idea here, if range() as mentioned by the other answers is not what you require.
I want the key to be "numbers" and the values to be 1, 2, 3 etc..
It's not exactly clear what you mean by this, but I'm guessing you might want the array keys to be the value of $numbers? In which case, you can modify your code as follows:
$number = (int)$_GET['tics'];
$items = array();
for ($numbers = 1; $numbers <= $number; $numbers++) {
$items[$numbers] = $numbers;
}
Your code should somewhat work as intended anyway (the numbers will be incorrect). The reason it doesn't is probably that $_GET['tics'] has no value. Ensure that you do indeed have tics in the $_GET array, and that you aren't actually POSTing (in which case you need $_POST['tics'] instead).
If you change $_GET in your code to $_POST and it still doesn't work, then tics is either not set or does not have a value greater than 0.

Random Numbers without duplication using an array in PHP

I'm trying to create a random number generator in PHP. It's supposed to generate three (3) numbers at a time, without repeat. That's to say, the 3 numbers cannot be the same.
Here's what I've tried so far:
$array = [];
$A = mt_rand(1,36);
$array[0] = $A;
$B = mt_rand(1,36);
$array[1] = $B;
if(in_array($B,$array)){
$B = mt_rand(1,36);
$array[1] = $B;
}
$C = mt_rand(1,36);
$array[2] = $C;
if(in_array($C,$array)){
$C = mt_rand(1,36);
$array[2] = $C;
}
$length = count($array);
//display the array values;
for($i = 0; $i < $length; $i++){
echo ($array[$i]."<br>");
}
Can anyone tell me where I'm going wrong?
Like this ( as per my initial comment ),
$array = [];
while( count($array) < 3 ){
$rand = mt_rand(1,36);
$array[$rand] = $rand;
}
print_r( $array );
By setting the "key" to be the random number, we can abuse the fact that associative array keys are unique. Then it's a simple matter of waiting until the array contains the desired amount of unique items.
You can test it here
Outputs: ( your results may vary, it's random )
Array
(
[16] => 16
[20] => 20
[27] => 27
)
UPDATE I was trying to think of a valid way to do it without using a loop ( on my way home from work ), and this way may be even better in some cases.
$a = range(1,36);
shuffle($a);
$array = array_slice($a, 0, 3);
print_r($array);
This will have better performance when the number of items you must find is higher. This is because there is no repetition, no collisions. So if you have a small range but need to find many items for the return, this will preform better. If you have many items and need to return only few, then the first one may be better, if not from speed then from memory use.
You can see it here
For reference this uses
range() - Create an array containing a range of elements.
http://php.net/manual/en/function.range.php
shuffle() - Shuffles (randomizes the order of the elements in) an array. It uses a pseudo random number generator that is not suitable for cryptographic purposes.
http://php.net/manual/en/function.shuffle.php
array_slice() - Returns the sequence of elements from the array as specified by the offset and length parameters.
http://php.net/manual/en/function.array-slice.php
So to explain this last one
First we create an array that contains each of our possible numbers as an element. So for example like this [1,2,3,4,5,6, ...].
Next we shuffle it which randomizes the order of the whole array. Shuffle modifies the array by "reference" so it doesn't return our array and therefor there is no assignment ( I think it returns Boolean, however I'm at a loss as to how it could fail and return false, pretty much it just returns true which we don't want to overwrite our array with ). So our example then becomes this [16,20,27,14,5,1, ...]
Last we cut out the number of items we need to return. Finally we end the example with this [16,20,27];
You can crunch the first one down into one ( really 2) line by assigning the value of the $rand variable in the condition of the loop. Like this:
$array = [];
while( count($array) < 3 && false !== ($rand = mt_rand(1,36))) $array[$rand] = $rand;
Because mt_rand(1,36) will never return boolan false. Also if I remember mt_rand is the same as rand now, or at least in current PHP versions.
Note: As of PHP 7.1.0, rand() uses the same random number generator as mt_rand(). To preserve backwards compatibility rand() allows max to be smaller than min as opposed to returning FALSE as mt_rand(). http://php.net/manual/en/function.rand.php
Hope it helps you, remember to think outside of the box.

php algorithm to divide and set numbers

I have an array which could be of any size coming from users.
The maximum size of values in each request to the API is 100 (from 0 - 99), a user could have ( it varies could be 64 or 137 or .... ) 234 values in his own array, what I want is to get the first hundred values, the next 100 values, then the next 34 values stored in an array or a string.
Something like ;
First Hundred : 0 - 99 //100
Second Hundred : 100 - 199 //100
Next Values : 200 - 234 //34
In each instance the values get appended to a string as seen below.
$lookupString = "";
//$notfm = one-dim array of values
for( $i = 0; $i <= 99; $i++ ){
$lookupString .= $notfm[$i].",";
}
$lookup = "http://api.lol.com/1/?user_ids=".$lookupString;
Can someone help me on this? I think this is easy but I'm missing something. Thanks.
Sample of the json encoded array can be found here
You want to use the array_chunk function.
http://php.net/manual/en/function.array-chunk.php
$request_bits = array_chunk($notfm, 100)
foreach ($request_bits as $request_bit) {
...
}
Alternately, you can set a separate condition to make the request when the counter is 100, empty the array of IDs, and empty the counter, but unless memory management is a huge issue array_chunk will do the trick.
You can use array_chunk() and implode().
$input_array;
// Split into chunks of 100
$chunks = array_chunk($input_array, 100);
foreach ($chunks as $chunk)
{
// Build the lookup string
$lookupString = implode(",", $chunk);
// DO LOOKUP HERE
}
Whenever I need to work with arrays, I open up the array functions manual page. A quick scan through the descriptions can often point you to an array function that does exactly what you want.
You want to get familiar with range() and array_chunk():
// make an array with all the numbers from 1 to 1000
$notfm = range(1,1000);
// make groups of 100 each
$chunks = array_chunk($notfm, 100);
// loop over each chunk of 100
foreach ($chunks as $lookupArray) {
$lookupString = implode(',', $lookupArray);
$lookup = "http://api.example.com/1/?user_ids=" . rawurlencode($lookupString);
// do stuff
}
Documentation: range(), array_chunk(), implode()
You can use array_slice
$first = array_slice( $input, 0, 100 );
$second = array_slice( $input, 100, 100 );
$third = array_slice( $input, 200, 34 );
And after goes the way what you want.

Adding an element to the beginning of an array without changing other array keys [duplicate]

This question already has answers here:
How to insert an item at the beginning of an array in PHP?
(8 answers)
Closed 1 year ago.
How can I add an element to the beginning of array without changing array key values in PHP?
To keep numerical keys from being reindexed, you could simply add the arrays together.
Instead of:
array_unshift($arr1, $arr2)
try:
$arr1 = $arr2 + $arr1;
If you use self-assigned (e.g. literal) keys, array_unshift() will do it.
If you use auto-generated (numeric) keys, how should that work? Use '-1' as the new first key?
EDIT:
Thank you to JasonS for pointing out an error in this answer.
ANY numeric key will be re-indexed by array_unshift(), no matter if it was auto-generated or self-assigned - if it's numeric, it'll get scrambled. See the link to the documentation above for details.
Use array_unshift(). (As mentioned, it will keep your string keys intact, but not numeric keys).
try this:
function array_insert(&$array, $insert, $position = -1) {
$position = ($position == -1) ? (count($array)) : $position ;
if($position != (count($array))) {
$ta = $array;
for($i = $position; $i < (count($array)); $i++) {
if(!isset($array[$i])) {
die(print_r($array, 1)."\r\nInvalid array: All keys must be numerical and in sequence.");
}
$tmp[$i+1] = $array[$i];
unset($ta[$i]);
}
$ta[$position] = $insert;
$array = $ta + $tmp;
//print_r($array);
} else {
$array[$position] = $insert;
}
//ksort($array);
return true;
}
Just a quick note for if you wish to use this in a loop...
As stated here: http://jp2.php.net/manual/en/function.array-unshift.php
array_unshift() prepends passed elements to the front of the array. Note that the list of elements is prepended as a whole, so that the prepended elements stay in the same order. All numerical array keys will be modified to start counting from zero while literal keys won't be touched.
TO give you an idea of how slow this is, we wrote some benchmark code (based on http://pastebin.com/Jad5TjsQ), and here is how it looks
mt#wizcorp-dev2:~/dev/test$ for d in arrayFillBrackets.php arrayFillPush.php arrayFillUnshift.php arrayFillPushReverse.php ; do cat $d; php $d; done
<?php
require "benchmark.php";
function ArrayFillBrackets()
{
$result = array();
for($i = 0; $i < 10000; $i++) $result[] = $i;
return $result;
}
$result = array();
$result[10]['ArrayFillBrackets'] = Benchmark('ArrayFillBrackets', null, 10);
!!! Benchmarking function ArrayFillBrackets for 10 iteration (args:null)...
===================
Results:
===================
time total: 0.02686286
time min: 0.00198293
time max: 0.0058589
time avg: 0.002686286
memory total: 0
memory min: 0
memory max: 0
memory avg: 0
<?php
require "benchmark.php";
function ArrayFillPush()
{
$result = array();
for($i = 0; $i < 10000; $i++) array_push($result, $i);
return $result;
}
$result = array();
$result[10]['ArrayFillPush'] = Benchmark('ArrayFillPush', null, 10);
!!! Benchmarking function ArrayFillPush for 10 iteration (args:null)...
===================
Results:
===================
time total: 0.03958679
time min: 0.003757
time max: 0.00485086
time avg: 0.003958679
memory total: 0
memory min: 0
memory max: 0
memory avg: 0
<?php
require "benchmark.php";
function ArrayFillUnshift()
{
$result = array();
for($i = 0; $i < 10000; $i++) array_unshift($result, $i);
return $result;
}
$result = array();
$result[1]['ArrayFillUnshift'] = Benchmark('ArrayFillUnshift', null, 1);
!!! Benchmarking function ArrayFillUnshift for 1 iteration (args:null)...
===================
Results:
===================
time total: 3.62487912
time min: 3.62487912
time max: 3.62487912
time avg: 3.62487912
memory total: 0
memory min: 0
memory max: 0
memory avg: 0
<?php
require "benchmark.php";
function ArrayFillPushReverse()
{
$result = array();
for($i = 0; $i < 10000; $i++) array_push($result, $i);
return array_reverse($result);
}
$result = array();
$result[10]['ArrayFillPushReverse'] = Benchmark('ArrayFillPushReverse', null, 10);
!!! Benchmarking function ArrayFillPushReverse for 10 iteration (args:null)...
===================
Results:
===================
time total: 0.05071593
time min: 0.00475311
time max: 0.00560999
time avg: 0.005071593
memory total: 108
memory min: 0
memory max: 24
memory avg: 10.8
mt#wizcorp-dev2:~/dev/test$
Please note that all tests are 10 * 10,000, except the array_unshift that runs 1 * 10,000 (was quite tired of waiting)... So again, don't use array_shift in iteration, as reversing the array only once costs almost nothing instead.
Adding my own (redundant) answer, because I tried to edit Martin's answer, using his original example, but it was rejected by others (not Martin). Maybe they didn't review the history of his answer, as I'm using his original example array and problem. Here is my rejected edit.
Kevin Wentworth's answer is correct.
Expanding on that answer using the original example from Martin's answer, if you have an array
$a = [1 => a, 2 => b, 5 => e, 6 => f, 8 => h, 9 => i];
and you want to take the last three items and prepend them to this same array, then you could do the following.
$a = array_slice($a, -3, null, true) + $a;
The resulting array is
array (6 => 'f', 8 => 'h', 9 => 'i', 1 => 'a', 2 => 'b', 5 => 'e',)
Notes
The true argument to array_slice preserves numeric keys (no such parameter exists for array_unshift).
Although array_slice doesn't remove anything from the original array, because of the behaviour of the + operator on arrays, the last three items are cancelled out.
From the docs for the + array operator
The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored.
array_unshift will not modify non numeric keys
Use array_unshift(); this will help u in adding element
Well, if you are doing what I am doing and creating a select form using results from the DB with indexes being the ids from the DB table, but want to add say "Any..." to the array with an index of 0, simply create the array variable with that item first, then populate the remaining values from the database. No need to unshift or order things after the database call.

Categories