Callback function using variables calculated outside of it - php

Basically I'd like to do something like this:
$arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$avg = array_sum($arr) / count($arr);
$callback = function($val){ return $val < $avg };
return array_filter($arr, $callback);
Is this actually possible? Calculating a variable outside of the anonymous function and using it inside?

You can use the use keyword to inherit variables from the parent scope. In your example, you could do the following:
$callback = function($val) use ($avg) { return $val < $avg; };
For more information, see the manual page on anonymous functions.
If you're running PHP 7.4 or later, arrow functions can be used. Arrow functions are an alternative, more concise way of defining anonymous functions, which automatically capture outside variables, eliminating the need for use:
$callback = fn($val) => $val < $avg;
Given how concise arrow functions are, you can reasonably write them directly within the array_filter call:
return array_filter($arr, fn($val) => $val < $avg);

use global variables i.e $GLOBAL['avg']
$arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
$GLOBALS['avg'] = array_sum($arr) / count($arr);
$callback = function($val){ return $val < $GLOBALS['avg'] };
$return array_filter($arr, $callback);

Related

Lambda equivalent from Python in PHP

I am trying to replicate this code in PHP:
pool = ThreadPool(num_parts)
pool.map(
lambda f: migrate(client, user_id=user_id, files=f), all_files)
What is the equivalent structure to use in PHP to iterate over an array while calling a function?
Double bonus points for using it in context of multi-threading on PHP :)
In Python, lambda creates an anonymous function at run time.
Say:
def f(x):
return x * 2
Or:
f = lambda x: x * 2
Will both create a function f that returns x times 2, except lambda can create an anonymous function, that can be assigned to a variable or passed as argument without being given a name.
A similar effect can be accomplished in PHP like this:
$f = function ($x) { return $x * 2; }
Now the variable $f is holding a function and can be used as $f(value).
The same way as in Python, you can create this anonymous function directly as an argument without assigning it to a variable or giving it a name. Example:
$arr = [1, 2, 3, 4, 5];
$arr = array_map(function ($x) { return $x * 2; }, $arr);
// $arr is now [2, 4, 6, 8, 10]
Iterate over a array while calling a function,
$array = array(1,2,3);
$var = 'foo';
array_walk($array, function ($value, $key) use ($var) {
# do something
});

How do I pass a PHP function expecting varargs a string?

I have a PHP function which takes a variable number of arguments.
function foo() {
$numargs = func_num_args();
if ($numargs < 3) {
die("expected number of args is 3, not " . $numargs);
}
...
If I call it like this:
foo(1, 12, 17, 3, 5);
it's fine, but if I call it like this:
$str = "1, 12, 17, 3, 5";
foo($str);
it fails because it says I am only passing one argument. What change do I need to make if I would prefer not to change the function itself, just the calling convention.
-- update: to save the explode call, I simply built an array. And because the function was a member function, the calling convention was a bit different. So the code wound up being
$list = array();
$list[] = 1;
$list[] = 12;
$list[] = 17;
// etc.
call_user_func_array(array($this, 'foo'), $list);
Thought this might be useful to someone else.
This should do the trick:
$str = "1, 12, 17, 3, 5";
$params = explode(', ', $str );
call_user_func_array ( 'foo', $params );
call_user_func_array() allows you to call a function and passing it arguments that are stored in a array. So array item at index 0 becomes the first parameter to the function, and so on.
http://www.php.net/manual/en/function.call-user-func-array.php
update: you will have to do some additional processing on the $params array if you wish that the arguments will be integers (they are passed as strings if you use the above snippet).
$str = "1, 12, 17, 3, 5";
call_user_func_array('foo',explode(',',$str));

Finding the index of an object in an array when there are multiple possibilities

I have an array, and I want to find all of the indexes of a certain object in the array. When I use array_search, it only returns the first index in which the object can be found.
echo array_search(3, array(3, 3, 4));
This returns 0, but I want to know that both indexes 0 and 1 have the integer 3 as their object. Is there a way of doing this without using a for loop?
Try array_keys() method :
$array = array(3, 3, 4);
print_r(array_keys($array, "3"));
For reference:
array_keys() — Return all the keys or a subset of the keys of an array Info & usuage examples : http://php.net/manual/en/function.array-keys.php
As an alternative to array_keys, array_filter() retains associativity
$key = 3;
$array = array(1, 3, 3, 4, 3, 5);
$result = array_filter(
$array,
function ($item) use ($key) {
return ($item == $key);
}
);
var_dump($result);

Opposite of array_intersect

I'm looking for the opposite of the function array_intersect, basically a function that returns the element that are not present in each of the provided arrays.
Example:
$a1 = array(1, 2, 3);
$a2 = array(2, 3, 4);
$result = array(1, 4);
I know how to do it programmatically (I just have two array so array_merge(array_diff($a1, $a2), array_diff($a2, $a1)) would do the job), but I'd like to know whether there's a built-in function that I can't find.
Thanks.
Since array_diff($a, $b) !== array_diff($b, $a)
the inverse of array_intersect is:
array_merge(array_diff($a,$b), array_diff($b,$a));
Here it is in a PHPUnit test format:
class ArrayInverseTest {
function testInverseArrayIntersect() {
$a = array(1, 2, 3);
$b = array(2, 3, 4);
$this->assertEquals(
array_values(array(1, 4)),
array_values(array_merge(array_diff($a, $b), array_diff($b, $a)))
);
}
}
It's not built in. Note that you can improve your solution:
array_merge($a1, array_diff($a2, $a1));
No there isn't builtin for that
I believe a language will never provide such a builtin function
Are you looking for array union? http://es.php.net/manual/en/language.operators.array.php

PHP min and max with array, is it reliable?

This works but, is it reliable? Will it always work since the MAINarray is containing ANOTHERarray which contains 2 values and min should work in MAINarray and find lowest value in its subarays.
$a[0]=array(0=>522,1=>'Truck');
$a[1]=array(0=>230,1=>'Bear');
$a[2]=array(0=>13,1=>'Feather');
$a[3]=array(0=>40,1=>'Rabit');
$z=min($a);$y=max($a);
echo "The easiest is ".$z[1]." with only ".$z[0]." pounds!<br>";
echo "The heaviest is ".$y[1]." with ".$y[0]." pounds!";
What you say?
Yes, it is reliable. It's safe to assume that min(array(1, 2, ..., n)) is equivalent to min(1, 2, ..., n), and the documentation specifically covers how min compares multiple arrays:
// With multiple arrays, min compares from left to right
// so in our example: 2 == 2, but 4 < 5
$val = min(array(2, 4, 8), array(2, 5, 1)); // array(2, 4, 8)
My understanding of how min works with your type of input is:
Only consider the arrays with the fewest number of items.
Compare the first elements
If there is a tie, compare the next element of each array. Repeat step.
e.g.:
array(
array(1, "A"),
array(2), // min
)
array(
array(1, "A"), // min
array(2, "A"),
)
array(
array(1, "Z"),
array(1, "A"), // min
)
I don't have a source for that information, but it's how I remember it working.
I’m not sure if this always works. In case of doubt just implement the function yourself:
function extremes($array, $key=0) {
if (count($array) === 0) return null;
$min = $max = null;
foreach ($array as &$val) {
if (!isset($val[$key])) continue;
if ($min > $val[$key]) $min = $val[$key];
else if ($max < $val[$key]) $max = $val[$key];
}
return array($min, $max);
}
$a = array(array(522, 'Truck'), array(230, 'Bear'), array(13, 'Feather'), array(40, 'Rabit'));
list($z, $y) = extremes($a);
The only evidence I could find to say it was intended to be able to use an array of arrays to compare is this bug report to improve the php docs. http://bugs.php.net/bug.php?id=50607
Although, it's quite unlikely for them to remove this functionality because of the way it has to compare arrays already by going into them recursively. The arguments list itself when using the function normally would be an array because there is no finite number of arguments.

Categories