Find array element with greatest or smallest sub-array element value - php

Element 1 of the following array represents the element with the greatest x value, and element 2 represents the element with the smallest x element.
Without looping over each array using PHP code, how can the index of the element with the greatest and smallest x be determined?
$array = [
['x'=>5,'y'=>3],
['x'=>9,'y'=>3],
['x'=>3,'y'=>3],
['x'=>7,'y'=>3]
];

Extract the x column and compute it:
$x = array_column($array, 'x');
$min = min($x);
$max = max($x);
Or, as JustOnUnderMillions points out:
list($min, $max) = [min($x=array_column($array, 'x')), max($x)];
To get the index of the array containing that value, just use array_search(). It will return the first key if there are multiple identical values:
$x = array_column($array, 'x');
$min = array_search(min($x), $x, true);
$max = array_search(max($x), $x, true);
PHP >= 5.5.0 needed for array_column() or use the PHP Implementation of array_column()

Related

Get n number of random values from an array and prevent consecutively repeated values

I want to populate a result array containing values randomly drawn from an input array, but the result array must not have two identical consecutive values.
Additional rules:
The input array of values will contain only unique values and will have at least two values to ensure that it is possible to populate the required result array.
The number of random values may be more or less than the size of the input array.
The result array must not require that all values from the input are used if the number of random values is greater than the input array's size. In other words, the randomly selected values must not be biased for even distribution.
Sample input:
$array = ['one', 'two', 'three', 'four'];
$n = 10;
A non-exhaustive list of possible valid results:
["three","one","three","one","two","one","four","one","three","four"]
["four","three","two","one","two","four","one","three","two","one"]
["two","four","three","one","two","one","four","two","three","one"]
This question was inspired by this deleted question which struggled to ask the question with clear rules and expectations.
To guarantee that the two consecutive values are not the same, keep track of the previous value (or its key) and remove it as a possible random value for the current iteration. Push the random value into the result array, then update the "previous" variable.
array_diff_key() can be used to exclude a specific key before calling array_rand() to return the random key.
Code: (Demo) (Reduced alternative) (The ugly version)
$lastIndex = -1;
$result = [];
for ($x = 0; $x < $n; ++$x) {
$key = array_rand(array_diff_key($array, [$lastIndex => null]));
$result[] = $array[$key];
$lastIndex = $key;
}
echo PHP_EOL . json_encode($result);
Alternatively, you can use unset() to exclude the previous random value, but it is important to not modify the original array or else there may not be enough values to fill the result array. Modifying a copy of the input array will do.
Code: (Demo)
$lastIndex = -1;
$result = [];
for ($x = 0; $x < $n; ++$x) {
$copy = $array;
unset($copy[$lastIndex]);
$key = array_rand($copy);
$result[] = $copy[$key];
$lastIndex = $key;
}
echo PHP_EOL . json_encode($result);

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.

Sorting a non-associative, multidimensional array

I found lots of info about sorting associative arrays but little about sorting non-associative ones. My array is structured/populated this way:
$my_array = array();
$my_array[0][0] = 'whatever3';
$my_array[0][1] = 3
$my_array[1][0] = 'whatever2';
$my_array[1][1] = 2
$my_array[2][0] = 'whatever1';
$my_array[2][1] = 1
I want to sort it by the second value to get:
$my_array[0][0] = 'whatever1';
$my_array[0][1] = 1;
$my_array[1][0] = 'whatever2';
$my_array[1][1] = 2;
$my_array[2][0] = 'whatever3';
$my_array[2][1] = 3;
How can this be achieved considering my array isn't associative?
What about:
usort($combined, function ($a, $b) { return $a[1] - $b[1]; });
With usort you provide a custom comparison function that must return:
0, if the elements must be considered equal.
a negative number, if the first element must be considered smaller than the second one.
a positive number, if the first element must be considered greater than the second one.
In this case, we choose to compare the second element of each item of $combined array.

PHP sort array of associative arrays by element size / string size

Is there a way to sort an array of associative arrays by the length of one of the elements? What I am trying to do is order the arrays by the largest to smallest description length.
$some_array = [];
$some_array[0] = ['name'=>'a name','description'=>'a description'];
$some_array[1] = ['name'=>'a name1','description'=>'a description 1'];
$some_array[2] = ['name'=>'a name2','description'=>'a description two for the third array element'];
$some_array[3] = ['name'=>'a name3','description'=>'a description three'];
With the above example $some_array[2] should come first followed by 3 then 1 then 0.
PHP >= 5.5.0 needed for array_column:
array_multisort(array_map('strlen', array_column($some_array, 'description')),
SORT_DESC,
$some_array);
Use usortto sort arrays based on custom parameters.
usort($array, function($a, $b) {
return strlen($b['description']) - strlen($a['description']);
});
var_dump($array)

Find shortest array count in multidimensional array

I have a multidimensional array:
$arr = array(
array('lions', 'tigers', 'bears'), // count = 3
array('dogs', 'cats'), // count = 2
array('horses', 'pigs', 'cattle', 'sheep', 'chickens') // count = 5
);
I want to return the array with the lowest count (I don't need to know the count, just need the array that HAS the lowest count). In this case, array('dogs', 'cats')
Right now I have:
$lowest = null;
foreach($nodePath as $arr)
{
$lowest = count($arr) < count($lowest) || $lowest == null ? $arr : $lowest;
}
This works but I'm wondering if I missed a more contained solution, perhaps using array_map, array_walk or a similar function.
Use array_map() with count as a callback to get the number of elements in each array, min() to get the smallest value. Then, to get the key of the smallest array - use array_flip() to flip the arrays keys and values, and access the $minth index. Now you can use the key to get the array you need:
$counts = array_map('count', $arr);
$min = min($counts);
$key = array_flip($counts)[$min];
$smallest_arr = $arr[$key];
Demo
Map your array to another array with counts of each child array. Get the key of the minimum value in this new array. Smallest array has the key of the minimum value:
$count = array_map('count', $arr);
$min = array_keys($count , min($count))[0];
var_dump($arr[$min]); // Array ( [0] => dogs [1] => cats )
Eval.in

Categories