My code:
function sortx($a, $b) {
if(!strpos($a["p_title"],'apple ipad')) {
return -1;
}
return 1;
}
usort($arr, 'sortx');`
In above function I want to pass:
$sort_text='apple ipad';
, when calling function instead of hardcoding apple ipad into strpos(). How can I accomplish that?
Call it with a closure:
$sort_text='apple ipad';
usort(
$arr,
function ($a, $b) use ($sort_text) {
if(!strpos($a["p_title"], $sort_text)) {
return -1;
}
return 1;
}
);
and you can pass additional arguments with the use clause
Related
I'm try to solve a task which uses new functions php7 uniform variable syntax nested () support foo()() (https://wiki.php.net/rfc/uniform_variable_syntax).
I need write function test for this code:
$sum = function($a, $b) { return $a + $b; };
test(6)(2)(3)($sum); // 11
test(3)(1)($sum); // 4
test(3)(3)('pow'); // 27
I don't found any explanation for this feature. Where can I find how to use it? I see that I must return function name in function test, but how to pass argument?
Thanks all for help. It's something like this:
<?php
function test($a) {
echo '<br/>';
$arr[] = $a;
return $mf = function($b) use(&$mf, &$a, &$arr) {
if(gettype($b) == 'object') {
echo(array_reduce($arr, $b));
} elseif (gettype($b) == 'string') {
if($b == 'pow') {
echo array_reduce($arr, function ($carry, $a) {
return !empty($carry) ? pow($carry, $a) : $a;
});
}
} elseif (gettype($b) == 'integer') {
$arr[] = $b;
}
return $mf;
};
}
$sum = function($a, $b) { return $a + $b; };
test(6)(2)(3)($sum); // 11
test(3)(1)($sum); // 4
test(3)(3)('pow'); // 27
This is more about nested recursive functions, or currying, than that rfc. That rfc just enabled the syntax that supported it.
This uses recursion until you pass a callable:
function test($var) {
$values = [$var];
$function = function($callback) use (&$values, &$function) {
if (is_callable($callback)) {
return array_reduce(array_slice($values, 1), $callback, $values[0]);
}
$values[] = $callback;
return $function;
};
return $function;
}
Because your functions expect two parameters but your nesting could have unlimited parameters, it's best to use an array and array reduce.
However, since multiplication functions like pow won't work with a null initial value, you can specify the initial value as the first passed parameter from the array.
I needed to merge and then sort two arrays with dissimilar data structures (can't be sorted in the MySQL query) but where both had a created_on field.
So I am using usort() with a custom function.
In my controller
usort(merged_array, 'sort_records');
In my helper functions
if(!function_exists('sort_records')){
function sort_records($a,$b){
if ( $a['created_at'] == $b['created_at'] )
return 0;
if ( $a['created_at'] < $b['created_at'] )
return -1;
return 1;
}
}
I would like to make this sort_records() function reusable. So I can use it with other arrays. Maybe something like..
function sort_records($a,$b,$index){
if ( $a[$index] == $b[$index] )
return 0;
if ( $a[$index] < $b[$index] )
return -1;
return 1;
Is this possible with usort() since when you call the function it does not take parameters at all? Is there another option?
You can create a class
class SortRecord
{
private $index;
public function __construct($index)
{
$this->index = $index;
}
public function sort_records($a, $b)
{
if ( $a[$this->index] == $b[$this->index] )
return 0;
if ( $a[$this->index] < $b[$this->index] )
return -1;
return 1;
}
}
then you can pass it to usort.
$obj = new SortRecord('created_at');
usort($merged_array, array($obj, 'sort_records'));
Put usort inside sort_records and use anonymous function, like so:
function sort_records(&$array,$index){
return usort($array, function ($a, $b) use ($index) {
if ( $a[$index] == $b[$index] )
return 0;
if ( $a[$index] < $b[$index] )
return -1;
return 1;
});
}
Then you can call it with whatever index you need
sort_records($array, 'created_at');
You could also use the use keyword on your usort, but you'd have to declare the inner function as anonymous :
function better_usort($array, $index) {
return usort($array, function($a, $b) use($index){
if ($a[$index] == $b[$index])
return 0;
if ($a[$index] < $b[$index])
return -1;
return 1;
});
}
And then you can call it with
better_usort($merged_array, 'created_at');
I would like to do something like this, but... working!
function _mathOperation($a, $b, $operation, $conversion)
{
return $operation($conversion($a), $conversion($b));
}
echo _mathOperation(4, 5, function($a, $b) { return $a+$b; }, intval);
echo _mathOperation(4.6, 5, function($a, $b) { return $a+$b; }, floatval);
I have the problem with passing intval and floatval as function parameter.
How do you do handle this?
you were missing the quotes around the function names:
function _mathOperation($a, $b, $operation, $conversion)
{
return $operation($conversion($a), $conversion($b));
}
echo _mathOperation(4, 5, function($a, $b) { return $a+$b; }, "intval");
// ^^ ^^
echo _mathOperation(4.6, 5, function($a, $b) { return $a+$b; }, "floatval");
// ^^ ^^
http://3v4l.org/AYiKN
You should pass the conversion parameter as the function name, rather than trying to pass the function.
e.g.
<?php
echo _mathOperation(4, 5, function($a, $b) { return $a+$b; }, 'intval');
Hi I have the following function:
foreach($array_1 as &$arr){
usort($arr,"cmp");
}
function cmp($a, $b) {
if ($a[2] == $b[2]) {
return 0;
}
return ($a[2] < $b[2]) ? -1 : 1;
}
If I do it like this it works, but if I put a variable instead of 2 which == 2 and a number the function doesn't work. Why is this and how can I work around it? I want to be able to change the number to sort an array based on variable input.
The code that doesn't work is:
$type = 2;
foreach($array_1 as &$arr){
usort($arr,"cmp");
}
function cmp($a, $b) {
if ($a[$type] == $b[$type]) {
return 0;
}
return ($a[$type] < $b[$type]) ? -1 : 1;
}
For PHP 5.3+, which hopefully you should be using, the solution is simple using a closure:
$index = 2;
foreach ($array_1 as &$arr) {
usort($arr, function ($a, $b) use ($index) {
return $a[$index] - $b[$index];
});
}
For PHP 5.2-, you could use global variables (YUCK!!) or a class:
class Sort {
protected $index;
public function __construct($index) {
$this->index = $index;
}
public function compare($a, $b) {
return $a[$this->index] - $b[$this->index];
}
}
$index = 2;
foreach ($array_1 as &$arr) {
usort($arr, array(new Sort($index), 'compare'));
}
I am using a uasort function like this:
uasort($entity_list, 'sortArray');
function sortArray($a, $b) {
if($a['fixed_column_name'] == $b['fixed_column_name']) {
return 0;
}
return ($a['fixed_column_name'] < $b['fixed_column_name']) ? -1 : 1;
}
I would like to pass a parameter to the sortArray function, like this:
uasort($entity_list, 'sortArray($arg)');
function sortArray($a, $b, $arg) {
$larg = $arg;
if($a[$larg] == $b[$larg]) {
return 0;
}
return ($a[$larg] < $b[$larg]) ? -1 : 1;
}
If you're using PHP 5.3+ (and you really should at this point in time), you can use closures:
uasort($entity_list, function ($a, $b) use ($arg) {
if ($a[$arg] == $b[$arg]) {
return 0;
}
return ($a[$arg] < $b[$arg]) ? -1 : 1;
});
Otherwise, you'll have to work around doing the same thing using global variables (oh noes!) or a class.
You could always use a class:
$sorter = new Sorter($arg);
usort($entity_list, array($sorter, "sort")); //will use $sorter->sort as callback
class Sorter {
function __construct($arg) {
$this->arg = $arg;
}
function sort($a, $b) {
// sort using $a, $b and $this->arg
}
}
Closures are nicer though ^^
Take a look at Example #4 using a closure on the usort() page of the PHP manual. The same technique can be used with all the basic sorts, including uasort()