array_rand - how can I get more values than array has? - php

I'm trying to get more random values than array has using array_rand. Is there any way to do it?
$amount = 6;
$numbers = array(
"10",
"20",
"30"
);
array_rand($numbers, $amount);
I can only get 3 values, because array has only 3 values. But what if I want to get like 6 values (of course if $qty > array has, will repeat but theres no problem)

Just use a custom solution that is not dependent on the features of array rand:
See it in action:
https://ideone.com/Kimjx4
// The quantity you want
$quantity = 6;
// the values to choose from
$numbers = array(
"10",
"20",
"30"
);
// get the keys so it will also work with associative arrays
$keys = array_keys($numbers);
// how many elements are there in our source array
$length = count($keys);
// where we store our result
$result = [];
// iterate for x quantity
for($c=0;$c < $quantity; $c++) {
// add random result from source to result array.
$result[] = $numbers[$keys[rand(0, $length-1)]];
}
var_dump($result);
if you want it as a function that also handles associative keys
https://ideone.com/SqTrKg
function getRandomResults(array $source, $quantity) {
$keys = array_keys($source);
// how many elements are there in our source array
$length = count($keys);
// where we store our result
$result = [];
// iterate for x quantity
for($c=0;$c < $quantity; $c++) {
// add random result from source to result array.
$result[] = $source[$keys[rand(0, $length-1)]];
}
return $result;
}
$res = getRandomResults([
"10",
"20",
"30"
], 6);
var_dump($res);

I'd like also to try))
function my_array_rand(array $arr, int $count): array
{
assert($count > 0);
if ($count <= count($arr)) {
return array_rand($arr, $count);
}
foreach (range(1, $count) as $index) {
$res[] = array_rand($arr, 1);
}
return $res ?? [];
}
$arr = [1,2,3,4,5,6,7];
var_dump(my_array_rand($arr, 100));

Related

Randomly interleave/zipper flat arrays without losing element order from original arrays

I want to merge / mix two arrays together, but I want it to be randomly "mixed" however NOT shuffled. For example:
$first = [1, 2, 3, 4];
$second = [10, 20, 30, 40];
Possible desired "mixes" are:
[1, 10, 20, 30, 2, 40, 3, 4]
[10, 1, 2, 20, 30, 3, 4, 40]
[1, 2, 3, 10, 20, 4, 30, 40]
Note that if we pluck the values back out we would still have the original orders of:
1, 2, 3, 4
10, 20, 30, 40
Well, there's (yet another) one possible approach:
$arr = call_user_func_array('array_merge', array_map(null, $first, $second));
print_r($arr); // [1, 10, 2, 20, 3, 30, 4, 40];
Demo. That's apparently deterministic; for random ordering each pair should be shuffled additionally. For example:
function zipShuffle($first, $second) {
return call_user_func_array('array_merge', array_map(function($a, $b) {
return mt_rand(0, 1) ? [$a, $b] : [$b, $a];
}, $first, $second));
}
... but that obviously won't be able to churn out something like [1,2,3,10,20...]. If this is required, here's another solution:
function orderedShuffle($first, $second) {
$results = [];
$stor = [$first, $second];
$i = mt_rand(0, 1);
// switching between arrays on the fly
while (list(, $v) = each($stor[$i])) {
$results[] = $v;
$i = mt_rand(0, 1);
}
// one array is gone, now we need to add all the elements
// of the other one (as its counter left where it was)
$i = 1 - $i;
while (list(, $v) = each($stor[$i])) {
$results[] = $v;
}
return $results;
}
Demo. The last function is actually quite easy to extend for as many arrays as required.
Can you try this,
<?php
$first = array(1,2,3,4);
$second = array(10,20,30,40);
$arrayMixed=array();
$firstReverse=array_reverse($first);
$secondReverse=array_reverse($second);
$firstReverseCount = count($firstReverse);
$secondReverseCount = count($secondReverse);
foreach($firstReverse as $key=>$val) {
if ($firstReverseCount>0) {
array_push($arrayMixed, array_pop($firstReverse));
if ($secondReverseCount>0) {
array_push($arrayMixed, array_pop($secondReverse));
}
}
}
$ArrayMixeddata = array_merge($arrayMixed, $second);
echo "<pre>";
print_r($ArrayMixeddata);
echo "</pre>";
?>
Not quick ways, but them works.
// with permutations
function combineShuffleOrder($first, $second)
{
// combine into one array with alternation
$firstLen = count($first);
$secondLen = count($second);
$max = max($firstLen, $secondLen);
$result = array();
for($i=0; $i < $max; $i++) {
if ($i < $firstLen)
$result[] = $first[$i];
if ($i < $secondLen)
$result[] = $second[$i];
}
// "shuffle" with permutation
$len = count($result);
for($i=1; $i<$len; $i++) {
if (rand(1, 3) % 2 == 0) {
$tmp = $result[$i-1];
$result[$i-1] = $result[$i];
$result[$i] = $tmp;
$i++; // skip one exchange
}
}
return $result;
}
// with using "shuffle" in subarray
function combineShuffleOrder2($first, $second)
{
// combine into one array with alternation
$firstLen = count($first);
$secondLen = count($second);
$max = max($firstLen, $secondLen);
$result = array();
for($i=0; $i < $max; $i++) {
$sub = array();
if ($i < $firstLen)
$sub[] = $first[$i];
if ($i < $secondLen)
$sub[] = $second[$i];
shuffle($sub);
$result = array_merge($result, $sub);
}
return $result;
}
// with using "shuffle" in subarray if sources arrays are equals by length
function combineShuffleOrder3($first, $second)
{
$max = count($first);
$result = array();
for($i=0; $i < $max; $i++) {
$sub = array(
$first[$i],
$second[$i]
);
shuffle($sub);
$result = array_merge($result, $sub);
}
return $result;
}
$first = array(1,2,3,4);
$second = array(10,20,30,40);
print_r(combineShuffleOrder($first, $second));
print_r(combineShuffleOrder2($first, $second));
print_r(combineShuffleOrder3($first, $second));
I recommend forming a single array of the two input arrays for simpler toggling. Simply loop and consume one element from a randomly selected array and push that selection into the result array. When the pool of arrays is reduced to a single array, kill the loop and append the remaining elements of the last surviving array onto the result array.
I'll use a pool of four arrays (one which is empty from the beginning) to demonstrate that the snippet is robust enough to handle a variable number of arrays, a variable number of elements in each array, and empty arrays.
Code: (Demo)
$first = [1, 2, 3, 4];
$second = [10, 20, 30, 40];
$third = [];
$fourth = ['a', 'b'];
$pool = [$first, $second, $third, $fourth];
$result = [];
while (count($pool) > 1) {
$pullFrom = array_rand($pool);
if (!$pool[$pullFrom]) {
unset($pool[$pullFrom]);
continue;
}
$result[] = array_shift($pool[$pullFrom]);
}
var_export(array_merge($result, ...$pool));
Alternatively without array_merge() and count() calls, but it makes more iterated calls of array_shift(): (Demo)
$pool = [$first, $second, $third, $fourth];
$result = [];
while ($pool) {
$pullFrom = array_rand($pool);
if (!$pool[$pullFrom]) {
unset($pool[$pullFrom]);
continue;
}
$result[] = array_shift($pool[$pullFrom]);
}
var_export($result);
Loop this script until both arrays are done.
$j = 0;
$i = 0;
$r = rand(0, 1);
if($r == 0) {
$ret .= $array1[$i];
$i++;
} elseif($r == 1) {
$ret .= $array2[$j];
$j++;
}
Of course, you have to handle a few exceptions in this code, but it might be the route.

Multiplying two arrays in php

I have a challenge multiplying two arrays.
this is what i intend doing
Array1 ( [0] => 2 [1] => 2 )
Array2 ( [0] => 8000.00 [1] => 1234.00 )
Every time i multiply this it breaks it down into 4 and returns a result as this
Array ( [0] => 16000 [1] => 16000 [2] => 2468 [3] => 2468 )
However when i pass single a single data it gets it right.
Here is my code, i'll appreciate any help i can get. Thanks
$total = array();
foreach($office_price as $price){
foreach($office_quantity as $quantity){
$total[] = $price * $quantity;
}
}
You can give multiple arrays to array_map, and it will process the corresponding elements:
$total = array_map(function($x, $y) { return $x * $y; },
$office_price, $office_quantity);
You loop through both arrays, so you get every value twice.
As you know, an array is built up using keys and values.
Use your foreach to that extent:
$total = array();
foreach ($office_price as $key=>$price) {
$total[] = $price * $office_quantity[$key];
}
You only need to loop one array, and by using the value from the second array with the same key, you get the proper result.
Use Array map function it will works
$total_hours = array(10, 20, 30);
$hourly_rate = array(15, 10, 15);
$total_pay = array_map(function($hour, $rate) {
return $hour * $rate;
}, $total_hours, $hourly_rate);
$total_in_array = array_map(function($x, $y) { return $x * $y; }, $office_price, $office_quantity); // This will return array of multiplied numbers
$total = array_sum($total_in_array); // This will return the total
Use this
$total = array();
for($i=0;$i<count($office_price);$i++){
$total[] = $office_price[$i] * $office_quantity[$i];
}
To multiply two arrays, you must do it elementwise: no nested loops involved. For example, if you want to get $total[2], then its value is $office_price[2] * $office_quantity[2]. Thus the one foreach loop. To loop through keys, use ... as $key => $price.
$office_price = array(10, 100, 1000);
$office_quantity = array(1, 2, 3);
$total = array();
foreach($office_price as $key => $price){
$total[$key] = $price * $office_quantity[$key];
}
var_dump($total);
// array(3) { [0]=> int(10) [1]=> int(200) [2]=> int(3000) }
$a= array (2,2);
$b= array(8000,1234);
$total = array();
for ($i=0;$i<count($a);$i++) {
$total[] = $a[$i] * $b[$i];
}
function a($a, $b)
{
$r = [];
for($i = 0; $i < (count($a)); $i ++)
{
$r[] = $a[$i] * $b[$i];
}
return $r;
}

Find the second highest variable in array

I would like to find the second highest variable in an array.
For example if I have:
$cookies = array(
"chocolate" => "20",
"vanilla" => "14",
"strawberry" => "18",
"raspberry" => "19",
"bluebery" => "29"
);
I can use max($cookies) to find the highest variable, which is "bluebery" => "29".
But how do I find the second highest? "chocolate" => "20"
Sort it and get the second item is the easiest way:
arsort($cookies);
$keys = array_keys($cookies);
echo $keys[1]; // chocolate
echo $cookies[$keys[1]]; // 20
If you want a more efficient way, you can also do it manually, by keeping track of both the highest and second-highest items at the same time:
function secondMax($arr) {
$max = $second = 0;
$maxKey = $secondKey = null;
foreach($arr as $key => $value) {
if($value > $max) {
$second = $max;
$secondKey = $maxKey;
$max = $value;
$maxKey = $key;
} elseif($value > $second) {
$second = $value;
$secondKey = $key;
}
}
return array($secondKey, $second);
}
Usage:
$second = secondMax($cookies);
echo "{$second[0]} => {$second[1]}"; // chocolate => 20
For fun you could use max() twice :)
For example:
Duplicate the array
Run max()
Remove the max
Run max() again
The alternative would to sort the array based on values and get the second element of the array. I'd be curious which is faster. Likely the sort.
arsort($cookies) AND array_shift($cookies) AND list($k, $v) = each($cookies);
echo "$k => $v"; // chocolate => 20
rsort($cookies);
echo $cookies[1];
Try :
asort($cookies);
end($cookies);
prev($cookies);
list($key,$value) = each($cookies);
or reverse it
arsort($cookies);
reset($cookies);
next($cookies);
list($key,$value) = each($cookies);
** Edit **
I thought I'd share this anyway, if someone would stumble across this and need it :
/**
* Returns the key => value pair with the specific rank.
* if $rank is 0, falase is returned. If $rank is positive,
* then the $rank th smallest pair is returned. If $rank
* is negative, then the $rank th biggest pair is returned.
* If $rank range is outside the size of the array, false
* is returned. If a callable function is provided, it will
* be used to sort the data. If $keySort is true, then the
* data will be sorted by keys instead (the callback functions
* will receive the keys to compare instead of values)
*
* #param $data array
* #param $rank int
* #param $cmd_function callable (optional)
* #param $keySort boolean (optional)
* #return array the key => value pair or false
*/
function findByRank($data, $rank, $cmd_function = null, $keySort = false) {
if (($rank == 0) || (abs($rank) > count($data))) {
return false;
}
$sort = ($keySort?'k':'a').'sort';
if ($cmd_function != null) {
$sort = 'u'.$sort;
$sort($data, $cmd_function);
} else {
$sort($data);
}
if ($rank > 0) {
reset($data);
$next = 'next';
} else {
end($data);
$next = 'prev';
$rank = abs($rank);
}
while (--$rank > 0) $next($data);
return each($data);
}
$cookies = array(
"chocolate" => "20",
"vanilla" => "14",
"strawberry" => "18",
"raspberry" => "19",
"bluebery" => "29"
);
header('Content-type:text/plain; charset=utf-8');
var_dump(findByRank($cookies, -10)); // -> false
var_dump(findByRank($cookies, -2)); // -> 'chocolate' key=>value pair
var_dump(findByRank($cookies, -1)); // -> 'blueberry' key=>value pair
var_dump(findByRank($cookies, 0)); // -> false
var_dump(findByRank($cookies, 1)); // -> 'vanilla' key=>value pair
var_dump(findByRank($cookies, 3)); // -> 'raspberry' key=>value pair
Sort the array descending and take the second value. Or, to be save, take the first value and go through the array until you find a smaller one.
function second_largest($arr)
{
sort($arr, SORT_NUMERIC);
return($arr[count($arr) - 2]);
}
//echo 3
echo second_largest(array(0, 3, 4, 1, 2));
Check this URL
http://maheshbokkisam.blogspot.in/2013/04/find-nth-highest-value-in-array-without.html
Find Nth/ N th highest value from given array without using any sorting in PHP
$ar = array(23,56,87,12,98,85,24,54,99,100,1,4,5,2,76,37,92);
$n = count($ar) - 5;
for($i = 0; $i < $n; $i++){
// Get the max value from array // get the Nth value from last loop
echo $a = max($ar);
echo "<br /><pre>"; print_r($ar);
$ar = array_flip($ar); // Flip the array
//print_r($ar);
unset($ar[$a]); // Unset the max value from array
//print_r($ar);
$ar = array_flip($ar); // Flip the array
echo "</pre>";
echo "<hr />";
}
<?php
// Finding Second highest number (In case of index of array is random)
$arr = [-5 => 33, -4 => -2, 8 => 0, 44, 44, 44, 44, 44];
$max = -INF;
$secondMax = -INF;
$size = sizeof($arr);
if ($size > 1) {
foreach ($arr as $key => $value) {
echo "KEY-> ", $key, "VALUE->", $value, "\n";
if ($value > $max) {
$max = $value;
} else {
if ($value < $max && $value > $secondMax) {
$secondMax = $value;
}
}
}
} else if ($size == 0) {
$max = "No Max element";
$secondMax = "No Second highest element";
} else {
foreach ($arr as $key => $value) {
$max = $arr[$key];
$secondMax = "No second highest element";
}
}
echo "maxvalue = ", $max, "\n";
echo "secondmax =", $secondMax;

PHP: Take several arrays, and make new ones based on shared indexes? [duplicate]

This question already has answers here:
Transposing multidimensional arrays in PHP
(12 answers)
Is there a php function like python's zip?
(14 answers)
Closed 10 months ago.
So, imagine you have 3 arrays:
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15
And you want to combine them into new arrays based on index:
1,6,11
2,7,12
3,8,13
4,9,14
5,10,15
What on earth could achieve this? Also, the total number of arrays is not known.
EDIT: Here's a snippet of my code so far (pulling data from a DB):
<?php
$ufSubmissions = $wpdb->get_results( $wpdb->prepare("SELECT * FROM wp_user_feedback WHERE user = '$ufUser' ORDER BY date DESC") );
$cleanedResponses = array();
foreach ($ufSubmissions as $submission) {
$cleanedResponses[] = unserialize($submission->responses);
}
array_map(null, $cleanedResponses));
?>
Doesn't seem to be working though, even $cleaned responses is an array of arrays.
Mostly like Alex Barrett's answer, but allows for an unknown number of arrays.
<?php
$values = array(
array(1,2,3,4,5),
array(6,7,8,9,10),
array(11,12,13,14,15),
);
function array_pivot($values)
{
array_unshift($values, null);
return call_user_func_array('array_map', $values);
}
print_r(array_pivot($values));
If your arrays are all the same length, you can pass as many as you want to the array_map function with null as the callback parameter.
array_map(null,
array(1, 2, 3, 4, 5),
array(6, 7, 8, 9, 10),
array(11, 12, 13, 14, 15));
The above will return the following two-dimensional array:
array(array(1, 6, 11),
array(2, 7, 12),
array(3, 8, 13),
array(4, 9, 14),
array(5, 10, 15));
This is a documented trick, so quite safe to use.
$ret = array();
for ($i =0; $i < count($input[0]); $i++){
$tmp = array();
foreach ($input as $array) {
$tmp[] = $array[$i];
}
$ret[] = $tmp;
}
Em... What's the problem? If they are equal sized, then you do
<?php
$a = array(1,2,3,4,5);
$b = array(6,7,8,9,10);
$c = array(11,12,13,14,15);
$d = array();
for ($i = 0; $i < sizeof($a); $i++) {
$d[] = array($a[$i], $b[$i], $c[$i]);
}
var_dump($d);
This is not tested, read it to get the idea instead of paste it.
The point is to put everything alltoghether in a feed and then redistribute it onto new arrays of a max length, the last one could not be full.
<?php
// initial vars
$max_size = 3; // of the new arrays
$total_array = $a + $b + $c; // the three arrays summed in the right order
$current_size = length($total_array);
$num_of_arrays = ceil($current_size / $max_size);
// redistributing
$result_arrays = array();
for($i = 0; $i < $num_of_arrays; $i++){ // iterate over the arrays
$new_array= array();
for($t = 0; $t < $max_size){
$pos = $num_of_arrays * $t + $i;
if(isset($total_array[$pos]) {
$new_array[] = $total_array[$pos];
}
}
$result_arrays[] = $new_array;
}
?>
// This takes an unlimited number of arguments and merges into arrays on index
// If there is only 1 argument it is treated as an array of arrays
// returns an array of arrays
function merge_on_indexes () {
$args = func_get_args();
$out = array();
if (count($args) == 1) for ($i = 0; isset($args[0][$i]); $i++) for ($j = 0; isset($args[0][$i][$j]); $j++) $out[$j][] = $args[0][$i][$j]; else for ($i = 0; isset($args[$i]); $i++) for ($j = 0; isset($args[$i][$j]); $j++) $out[$j][] = $args[$i][$j];
return $out;
}
// Usage examples
// Both return array('data1','data3','data5'),array('data2','data4','data6')
$arr1 = array('data1','data2');
$arr2 = array('data3','data4');
$arr2 = array('data5','data6');
$result = merge_on_indexes($arr1,$arr2);
print_r($result);
$multiDimArr = array(
array('data1','data2'),
array('data3','data4'),
array('data5','data6')
);
$result = merge_on_indexes($multiDimArr);
print_r($result);
$arr = get_defined_vars(); //gets all your variables
$arrCount = 0;
$arrOfarrs = array();
foreach($arr as $var){ //go through each variable
if(is_array($var)){ //and see if it is an array
$arrCount++; //we found another array
for($i == 0;$i < count($var); $i++){ //run through the new array
$arrOfarrs[$i][] == $var[$i]; //and add the corresponding elem
}
}
}

How do I select random values from an array in PHP?

I have an array of objects in PHP. I need to select 8 of them at random. My initial thought was to use array_rand(array_flip($my_array), 8) but that doesn't work, because the objects can't act as keys for an array.
I know I could use shuffle, but I'm worried about performance as the array grows in size. Is that the best way, or is there a more efficient way?
$result = array();
foreach( array_rand($my_array, 8) as $k ) {
$result[] = $my_array[$k];
}
$array = array();
shuffle($array); // randomize order of array items
$newArray = array_slice($array, 0, 8);
Notice that shuffle() function gives parameter as a reference and makes the changes on it.
You could use array_rand to pick the keys randomly and a foreach to gather the objects:
$objects = array();
foreach (array_rand($my_array, 8) as $key) {
$objects[] = $my_array[$key];
}
What about?:
$count = count($my_array);
for ($i = 0; $i < 8; $i++) {
$x = rand(0, $count);
$my_array[$x];
}
I just found this in our code and was hoping to find a more readable solution:
$rand = array_intersect_key($all, array_flip(array_rand($all, $count)));
You can get multiple random elements from an array with this function:
function getRandomElements(array $array): array
{
$result = [];
$count = count($array);
for ($i = 0; $i < rand(0, $count); $i++) {
$result[] = rand(0, $count);
}
$result = array_unique($result);
sort($result);
return $result;
}

Categories