Say I have this array:
$array[] = 'foo';
$array[] = 'apple';
$array[] = '1234567890;
I want to get the length of the longest string in this array. In this case the longest string is 1234567890 and its length is 10.
Is this possible without looping through the array and checking each element?
try
$maxlen = max(array_map('strlen', $ary));
Sure:
function getmax($array, $cur, $curmax) {
return $cur >= count($array) ? $curmax :
getmax($array, $cur + 1, strlen($array[$cur]) > strlen($array[$curmax])
? $cur : $curmax);
}
$index_of_longest = getmax($my_array, 0, 0);
No loop there. ;-)
A small addition to the ticket. I came here with a similar problem: Often you have to output just the longest string in an array.
For this, you can also use the top solution and extend it a little:
$lengths = array_map('strlen', $ary);
$longestString = $ary[array_search(max($lengths), $lengths)];
Loop through the arrays and use strlen to verify if the current length is longer than the previous.. and save the index of the longest string in a variable and use it later where you need that index.
Something like this..
$longest = 0;
for($i = 0; $i < count($array); $i++)
{
if($i > 0)
{
if(strlen($array[$i]) > strlen($array[$longest]))
{
$longest = $i;
}
}
}
This way you can find the shortest (or longest) element, but not its index.
$shortest = array_reduce($array, function ($a, $b) {
if ($a === null) {
return $b;
}
return strlen($a) < strlen($b) ? $a : $b;
});
Related
I'm trying to find a way to replace any duplicated value but the only solution I have found so far is array_unique which doesn't really work for me as I need the duplicate to be replaced by another number which itself is not a duplicate.
function generate_random_numbers($rows, $delimiter)
{
$numbers = array();
for($i = 0; $i < $delimiter; $i++)
{
$numbers[$i] = rand(1, $rows);
if(in_array($i, $numbers))
{
$numbers[$i] = rand(1, $row);
}
}
return $numbers;
}
$numbers = generate_random_numbers(20, 10);
print_r($numbers);
would anyone help me out on this one please?
You can do this way easier and faster.
Just create an array for all possible numbers with range(). Then shuffle() the array and take an array_slice() as big as you want.
<?php
function generate_random_numbers($max, $amount) {
if($amount > $max)
return [];
$numbers = range(1, $max);
shuffle($numbers);
return array_slice($numbers, 0, $amount);
}
$numbers = generate_random_numbers(20, 10);
print_r($numbers);
?>
And if you want to get 490 unique elements from a range from 1 - 500, 10'000 times:
My version: ~ 0.7 secs
Your version: Order 2 birthday cakes, you will need them.
You are inserting a random number and then, if it is already in the array (which it MUST be because you just inserted it), you use a new random number, which might be a duplicate. So, you have to get a number that is not a duplicate:
do {
$num = rand(1,$rows);
} while(!in_array($num, $numbers));
Now, you know that $num is not in $numbers, so you can insert it:
$numbers[] = $num;
You were pretty close.
The if-clause needs to be a loop, to get new random number.
(Also your in_array was slightly wrong)
function generate_random_numbers($rows, $delimiter) {
$numbers = array();
for($i = 0; $i < $delimiter; $i++) {
do {
$number = rand(1, $rows);
}
while(in_array($number, $numbers));
$numbers[] = $number;
}
return $numbers;
}
So I have an array:
$array = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
Obviously they're indexed 0-6.
I want to feed in a specific key index, and then reorder the array, beginning with that key, then going through the rest in the same order, like so:
print_r(somefunction(3, $array));
which would print this:
array
(
'0'=>'Wed',
'1'=>'Thu',
'2'=>'Fri',
'3'=>'Sat',
'4'=>'Sun',
'5'=>'Mon',
'6'=>'Tue'
)
Is there a core function that would do this, or does anyone have a quick solution?
UPDATE
Here's my final function, slightly bigger in scope than my question above, which utilizes AbraCadaver's answer:
public static function ordered_weekdays($format = 'abr')
{
$array = $format == 'full' ? array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') : array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
return array_merge(array_splice($array, get_option('start_of_week'), count($array)-1), $array);
}
Because it's a nice one-liner, I didn't need to make it a separate function.
I've done this before and thought it was simpler than this, but here is what my brain says at the moment:
$index = 3;
$array = array_merge(array_splice($array, $index, count($array)-1), $array);
Try something along these lines...
function reorder($x,$y)
{
$c = count($y);
for ($i=0; $i<$c; $i++)
{
$newArray[$i] = $y[$x];
$x++;
if ($x > $c) $x = 0;
}
return($newArray);
}
function somefunction($n, array $a) {
$x = array_slice($a, 0, $n);
$y = array_slice($a, $n);
return array_merge($y, $x);
}
// forget this: uneccessary looping...
function somefunction($n, array $a) {
for($i = 0; $i < $n; $i++) {
array_push($a, array_shift($a));
}
return $a;
}
I want to tell my array to start from key position 2 and then loop through the entire array, including the values before key position 2. I just want to use one array and specify the key position I start looping from. For example, here I am using array_splice, but it does not do what I want it to, could you help me please?
$names = array('Bill', 'Ben', 'Bert', 'Ernie');
foreach(array_slice($names, 2) as $name){
echo $name;
}
foreach(array_slice($names, 3) as $name){
echo $name;
}
If the keys are irrelevant, you can splice the array twice, and merge the resulting arrays, like this:
$names = array('Bill', 'Ben', 'Bert', 'Ernie');
$start = 2;
foreach( array_merge( array_slice($names, $start), array_slice( $names, 0, $start)) as $name){
echo $name;
}
You can see from the demo that this prints:
BertErnieBillBen
Alternatively, for efficiency, you can use two loops that are aware of wrapping around to the beginning, which will be more efficient since you are operating on the original array and not creating copies of it.
$start = 2;
for( $i = $start, $count = count( $names); $i < $count; $i++) {
echo $names[$i];
}
$i = 0;
while( $i < $start) {
echo $names[$i++];
}
You could also turn this into one single loop, and just encapsulate the logic for wrapping around inside the for.
$limit = 2; //so you can set your start index to an arbitrary number
$fn= function($a,$b) use ($limit){
if(($a < $limit && $b < $limit)
|| ($a >= $limit && $b >=$limit)) //$a and $b on the same side of $limit
return $a < $b ? -1 : ($a==$b ? 0 : 1);
if($a < $limit && $b > $limit) return 1; //because $a will always be considered greater
if($a >= $limit && $b < $limit) return -1; //because $b will always be considered greater
};
uksort($arr, $fn);
foreach($arr as $v) echo $v;
I need to rewrite some Python code into PHP (don't hate me, a customer asked me to do so)
In Python you can do something like this:
// Python
numbers = [34.6, -203.4, 44.9, 68.3, -12.2, 44.6, 12.7]
positive = [int(n) for n in numbers if n > 0]
negative = [int(n) for n in numbers if n < 0]
But if you try something like this in PHP it doesn't work:
// PHP
$numbers = array(34.6, -203.4, 44.9, 68.3, -12.2, 44.6, 12.7);
$positive = array(intval($n) for $n in $numbers if $n > 0);
$negative = array(intval($n) for $n in $numbers if $n > 0);
Instead of doing something like:
<?php
$numbers = array(34.6, -203.4, 44.9, 68.3, -12.2, 44.6, 12.7);
$positive = array();
$negative = array();
foreach($numbers as $n) {
if($n > 0):
$positive[] = intval($n);
else:
$negative[] = intval($n);
endif;
}
?>
Is there a way to write this with less code like you can do in Python?
You can use array_filter and anonymous functions (the latter only if you have PHP 5.3 or higher), but the way that you showed with more code is more efficient and looks neater to me.
$positive = array_filter($numbers, function($x) { return $x > 0; });
$negative = array_filter($numbers, function($x) { return $x < 0; });
And array_map to apply intval:
$positive = array_map('intval', array_filter($numbers, function($x) { return $x > 0; }));
$negative = array_map('intval', array_filter($numbers, function($x) { return $x < 0; }));
Sure. Use array_filter
$positive = array_filter($numbers,function($a) {return $a > 0;});
$negative = array_filter($numbers,function($a) {return $a < 0;});
PHP is a bit more verbose in the array / map handling, it's one of Python's strengths. There are some functions that can help with dealing with arrays, like for instance:
$positive = array_filter($numbers,function($n){return $n > 0;});
$positive = array_map('intval',$positive);
$negative = array_filter($numbers,function($n){return $n < 0;});
$negative = array_map('intval',$positive);
No... As far as I am aware, foreach loop is the only way to go.
And this is not that much more of code.
But if you want to make it a little shorter, you can get rid of explicit array declarations just before the foreach loop.
This is more of a conceptual question concerning the built in functionality of PHP and arrays. I was wondering if there is any way to do the following:
You have an array $a and this array contains 5 elements (0-4) for the purpose of this example.
Is there any way to make a new array, which would contain the following:
$b[0] = $a[0];
$b[1] = $a[0] + $a[1];
$b[2] = $a[0] + $a[1] + $a[2];
$b[3] = $a[0] + $a[1] + $a[2] + $a[3];
$b[4] = $a[0] + $a[1] + $a[2] + $a[3] + $a[4];
etc..
I imagine an example of it's use would be bread crumbs on a website, where you could click on any directory of a given link like /dir1/dir2/dir3/dir4
Is there anything built into PHP that can handle building up an array in this fashion? Or examples of a function which handles this? Or even a better way to go about this.
Thanks!
EDIT: Here is the final solution via the help of you guys! This will build the link, and create the proper link for each directory/element.
//$a is our array
$max = count($a);
foreach (range(1,$max) as $count) {
$b[] = implode("/", array_slice($a, 0, $count));
}
foreach($b as $c) {
$x = explode('/' , $c);
$y = array_pop($x);
echo "<a href='$c'>".$y."</a>"."/";
}
If you just want the five combinations as in your example then:
foreach (range(1,5) as $count) {
$b[] = implode("/", array_slice($a, 0, $count));
}
You'd be best with a recursive function in that case.
$arr = array('dir1', 'dir2', 'dir3', 'dir4', 'dir5');
function breadcrumbs($a)
{
// Remove first value
$first = array_shift($a);
// Loop through other values
foreach ($a as $key => $value)
{
// Add first to remaining values
$a[$key] = $first . '/' . $value;
}
// Return array
return array($first) + breadcrumbs($a);
}
Untested, but should work. It will make each sequential value contain the values before it in the array.
$b = array();
for($i=0;$i<count($a);$i++) {
$b[] = array_sum(array_splice($a,0,$i));
}
I think, you want something like this:
for($i = 0; $i < count($a); $i++)
for($j = 0; $j < i + 1; $j++)
$b[i] += $a[j];