Insert new element in an array - php

EDITED
$queryPremium ="Select * from tablename where premium = 1 order by id desc";
$rowPremium = mysql_query($queryPremium);
$queryNotPremium ="Select * from tablename where premium = 0 order by id desc";
$rowNotPremium = mysql_query($queryNotPremium);
now i want a single array where the order of the rowNotPremium will be maintained and $rowPremium will be inserted randomly after 2 data of $rowNotPremium or after 3data of $rowNotPremium...
How to do that?

you can do this:
$newArray = $nonpremium + $premium
or
$newArray = array_merge($nonpremium, $premium)

Sorry for any bad practice here if you feel this can be edited please edit it...
<?php
$arr_a = array('1','2','3','4','5','6');
$arr_b = array('apples','oranges','bananas','peaches');
// How many elements are in the array we are inserting into
$count = count($arr_a);
// What was the last insert position? Make sure the next will be greater than this
$prev = 0;
// Loop through each of our elements to insert
foreach($arr_b as $value)
{
// Generate a random value, higher than the previous
// random number but still less than count($arr_a)
$rand = rand($prev, $count);
// Store this as the previous value + 1
$prev = $rand + 1;
// Insert our value into $arr_a at the random position
array_splice($arr_a, $rand, 0, $value);
}
echo "<pre>".print_r($arr_a, true)."</pre>";

Use array_splice() and rand() functions
$array1 = array( 1,2,3,4,5 );
$array2 = array( 6,7,8,9 );
array_splice( $array1, rand(0,count($array2)-1), 0, $array2 ); // splice in at random position

Related

shuffle an array with a "limit" in PHP

What I try to achieve: randomize the order of all elements in an array, but allow each element to change its position only by a limited number of "steps".
Say I have an array like below, and I wish to randomize with a limit of 2 steps:
$array = [92,12,2,18,17,88,56];
An outcome could be: [2,12,92,17,18,56,88] (all elements of the array moved a maximum of 2 steps), but it could not be: [56,92,2,12,17,18,88] because in this example 56 moved too far.
I considered using a combination of array_chunk and shuffle, but this is problematic because elements will be shuffled inside their chunk, resulting in elements at the beginning or end of a chunk only moving in one direction. This is what I came up with (and problematic):
// in chunks of 3 an element can move a max. of 2 steps.
$chunks = array_chunk($array, 3);
$newChunks = [];
foreach ($chunks as $chunk){
$keys = array_keys($chunk);
shuffle($keys);
$newChunk = [];
foreach ($keys as $key){
$newChunk[$key] = $chunk[$key];
}
$newChunks[] = $newChunk;
}
Another idea I had was to get the key of the item in the array and with rand add of subtract my limit. For example:
foreach ( $array as $key => $value ) {
$newArray[] = ["key" => $key+rand(-2,2), "value" => $value];
};
This creates a new array with each of its elements being an array with the original value plus a value key that is the original key plus or minus 2. I could flatten this array, but the problem with this is that I can have duplicate keys.
I created this function to do this, but I guess it needs more improvements:
/**
* #param array $array
* #param int $limit
* #return array
*/
function shuffleArray(array $array, int $limit): array
{
$arrayCount = count($array);
$limit = min($arrayCount, $limit);
for ($i = 0; $i < $limit; $i++) {
for ($j = 0; $j < $arrayCount;) {
$toIndex = min($arrayCount - 1, $j + rand(0, 1));
[$array[$j], $array[$toIndex]] = [$array[$toIndex], $array[$j]];
$j += (($toIndex === $j) ? 1 : 2);
}
}
return $array;
}
Test:
$array = [92, 12, 2, 18, 17, 88, 56];
$limit = 2;
$result = shuffleArray($array, $limit); // [12, 92, 17, 2, 18, 56, 88]
Here is a possible solution in one pass :
Try to swap each element at position i with an element between i (stay in place) and i+x. I look only forward to avoid swaping an element several times. And I need an extra array to flag the already swapped elements. I don't need to process them in the future as they were already moved.
function shuffle_array($a, $limit)
{
$result = $a ;
$shuffled_index = array() ; // list of already shuffled elements
$n = count($result);
for($i = 0 ; $i < $n ; ++$i)
{
if( in_array($i, $shuffled_index) ) continue ; // already shuffled, go to the next elements
$possibleIndex = array_diff( range($i, min($i + $limit, $n-1)), $shuffled_index) ; // get all the possible "jumps", minus the already- shuffled index
$selectedIndex = $possibleIndex[ array_rand($possibleIndex) ]; // randomly choose one of the possible index
// swap the two elements
$tmp = $result[$i] ;
$result[$i] = $result[$selectedIndex] ;
$result[$selectedIndex] = $tmp ;
// element at position $selectedIndex is already shuffled, it needs no more processing
$shuffled_index[] = $selectedIndex ;
}
return $result ;
}
$array = [92,12,2,18,17,88,56];
$limit = 2 ;
shuffle_array($array, $limit); // [2, 18, 92, 12, 17, 56, 88]
I expect more elements to stay in place than in the solution of Kerkouch, as some elements can have very few remaining free choices.

Array of Values from SQL showing which exist and which don't

I couldn't think of a title, I know it's not good.
Basically, I'm going to have an array of values POSTed to me. These values will be integers.
So, let's say it will be 1,2,3,4,5 etc.. I've already figured out how to get their respective values from the database like such
$values = explode(",", $_GET['id']);
$placeholders = str_repeat('?, ', count($values) - 1) . '?';
$CheckQuery = $database->prepare("SELECT * FROM users WHERE the_id IN($placeholders)");
$CheckQuery->execute($values);
$Res = $CheckQuery->fetchAll(PDO::FETCH_ASSOC);
Now, this is great because given the IDs I want to be able to return:
ID1:0or1
ID2:0or1
I'm stuck trying to figure out how to return the IDs which do not exist in the database though. Any help here?
If you want 1 or 0, you can use the results of the $values array and the data from the database $Res, create arrays keyed on these lists (1's for $Res and 0's for $values) then overwrite the 0's with the 1's found in the database...
$present = array_fill_keys(array_column($Res, 'the_id'), 1);
$allValues = array_fill_keys($values, 0);
$result = array_replace($allValues, $present);
with some test data...
$_GET['id'] = '1,2,3';
$values = explode(",", $_GET['id']);
$Res = [ ['the_id' => 1], ['the_id' => 3]];
$present = array_fill_keys(array_column($Res, 'the_id'), 1);
$allValues = array_fill_keys($values, 0);
$result = array_replace($allValues, $present);
print_r($result);
you get
Array
(
[1] => 1
[2] => 0
[3] => 1
)
$values = explode(",", $_GET['id']);
$placeholders = str_repeat('?, ', count($values) - 1) . '?';
// select `the_id` as you don't need other fields in select
$CheckQuery = $database->prepare("SELECT the_id FROM users WHERE the_id IN($placeholders)");
$CheckQuery->execute($values);
// Use `FETCH_COLUMN` to fetch ids as array:
$ids = $CheckQuery->fetchAll(PDO::FETCH_COLUMN, 0);
// Now you can use `array_diff` to get ids
// that are in `$values` and not in `$ids`
print_r(array_diff($values, $ids));

Array with only 10 most recent values

I have an array with multiple elements. I want to keep only the 10 most recent values. So I am reversing the array in a loop, checking if the element is within the first 10 range and if not, I unset the element from the array.
Only problem is that the unset does not work. I am using the key to unset the element, but somehow this does not work. The array keeps on growing. Any ideas?
$currentitem = rand(0,100);
$lastproducts = unserialize($_COOKIE['lastproducts']);
$count = 0;
foreach(array_reverse($lastproducts) as $key => $lastproduct) {
if ($count <= 10) {
echo "item[$key]: $lastproduct <BR>";
}
else {
echo "Too many elements. Unsetting item[$key] with value $lastproduct <BR>";
unset($lastproducts[$key]);
}
$count = $count + 1;
}
array_push($lastproducts, $currentitem);
setcookie('lastproducts', serialize($lastproducts), time()+3600);
I'd use array_slice ( http://php.net/array_slice ) perhaps like:
$lastproducts = unserialize($_COOKIE['lastproducts']);
// add on the end ...
$lastproducts[] = $newproduct;
// start at -10 from the end, give me 10 at most
$lastproducts = array_slice($lastproducts, -10);
// ....
You can use array_splice($input, $offset) function for this purpose.
$last_items_count = 10;
if(count($lastproducts) >= $last_items_count) {
$lastproducts = array_splice($lastproducts, count($lastproducts) - $last_items_count);
}
var_dump($lastproducts);
I hope this code helps.
For more information, here is the documentation:
http://php.net/manual/en/function.array-splice.php
I think a better way to select last 10 is:
$selection = array();
foreach(array_reverse($lastproducts) as $key => $lastproduct) {
$selection[$key] = $lastproduct;
if (count($selection)>=10) break;
}
Finally, $selection will have last 10 (or less) products.
Works great using array_splice and array_slice, thanks! :)
$lastproducts = unserialize($_COOKIE['lastproducts']);
// remove this product from array
$lastproducts = array_diff($lastproducts, array($productid));
// insert product on first position in array
array_splice($lastproducts, 0, 0, $productid);
// keep only first 15 products of array
$lastproducts = array_slice($lastproducts, 0, 15);

PHP - How to store distinct values so that while loop will not reiterate previous loops

I want my array to echo out only distinct values.
Here are my php codes so far:
$get_con = mysqli_query($con, "SELECT * FROM messages WHERE from_id='$my_id' OR to_id='$my_id' ");
$last_select_id = "";
while ($run_con = mysqli_fetch_array($get_con)) {
$from_id = $run_con['from_id'];
$to_id = $run_con['to_id'];
//This just ensures that it echos the other person's id and not my own
if ($from_id == $my_id) {
$select_id = $to_id;
} else {
$select_id = $from_id;}
//Trying to save the iterations
if ($select_id != $last_select_id) {
$last_select_id = $select_id;
echo "$select_id<br/>";
}
}
For example, my array has: 1, 1, 2, 3, 4, 2, 4.
My codes will return as: 1, 2, 3, 4, 2, 4
I want: 1, 2, 3, 4
The problem is that 2 and 4 are being repeated twice.
The statement, "if ($select_id != $last_select_id) {" is stopping "1" from being repeated twice in the beginning. This means that my if statement can only store $last_select_id only once for the previous iteration. I've searched for two days but couldn't find an answer. I would appreciate any help! Thank you.
There are a couple of approaches you can use.
In PHP, you can create an array, and place each entry into the array as it's returned/echoed/whatever.
$array = array( 1,1,2,3,4,4,5 );
$seen = array();
foreach ( $array as $arr ) {
if ( !in_array( $arr, $seen )) {
echo $arr.PHP_EOL;
$seen[] = $arr;
}
}
Of course, it's probably better to not have duplicate entries in the array, anyway. In PHP, you can use array_unique() for that:
$array = array( 1,1,2,3,4,4,5 );
$array = array_unique( $array );
foreach ( $array as $arr ) echo $arr.PHP_EOL;
But probably even better than THAT is to simply not have duplicates in your array to begin with. Look at "SELECT DISTINCT " in your SQL for that....
PHP has a function for this
array_unique($array)
Documentation here.
In your case it would be
$temp_array = array_unique(mysqli_fetch_array($get_con));
foreach($temp_array as $temp) {
*stuff*
}
I would use the SELECT DISTINCT statement in my query:
//I'm assuming you have a column called "id"
$get_con = mysqli_query($con, "SELECT DISTINCT id FROM messages WHERE from_id='$my_id' OR to_id='$my_id' ");
Info on SELECT DISTINCT can be found here: http://www.mysqltutorial.org/mysql-distinct.aspx
From there you can just do the following to output all the id's:
foreach($id in $get_con){
echo $id
}
You can also adjust for needs as you see fit.

How do I count comma-separated values in PHP?

I have a variable holding values separated by a comma (Implode), and I'm trying to get the total count of the values in that variable. However. count() is just returning 1.
I've tried converting the comma-separated values to a properly formatted array which still spits out1.
So here is the quick snippet where the sarray session is equal to value1,value2,value3:
$schools = $_SESSION['sarray'];
$result = count($schools);
You need to explode $schools into an actual array:
$schools = $_SESSION['sarray'];
$schools_array = explode(",", $schools);
$result = count($schools_array);
if you just need the count, and are 100% sure it's a clean comma separated list, you could also use substr_count() which may be marginally faster and, more importantly, easier on memory with very large sets of data:
$result = substr_count( $_SESSION['sarray'], ",") +1;
// add 1 if list is always a,b,c;
Should be
$result = count(explode(',',$schools));
Actually, its simpler than that:
$count = substr_count($schools, ',') + 1;
If there is sarray key set in session array, the count will return 1 for an empty string as well.
$session = array('sarray' => '');
$count = count(explode(',', $session['sarray']));
echo $count;
// => 1
So, if you want to count the number of items in the array, you will have to add an additional check for empty.
$session = array('sarray' => '');
$count = !empty($session['sarray']) ? count(explode(',', $session['sarray'])) : 0;
echo $count;
// => 0
Now, let's check if this works with items inside sarray.
$session = array('sarray' => 'foo, bar');
$count = !empty($session['sarray']) ? count(explode(',', $session['sarray'])) : 0;
echo $count;
// => 2
Hope this helps.
$schools = $_SESSION['sarray'];
$array = explode(',', $schools); array_walk($array, 'trim');
$count = count($array);
The array_walk($array, 'trim') will remove any trailing space in elements value. :)

Categories