Basic question really, I know I can do this in some other languages but I dont know PHP that well, hoping someone can help.
So I have the following.
$holyToT *=100;
$coldToT *=100;
$fireToT *=100;
$poisonToT *=100;
$lightningToT *=100;
And I want to be able to just condense it down to something like:
$holyToT, $coldToT, $fireToT, $poisonToT, $lightningToT *= 100;
Does PHP have an internal way of doing something similar?
I agree with the others, but if you really want to have it in one line, you could do something like this:
list($holyToT, $coldToT, $fireToT, $poisonToT, $lightningToT) = array_map(function($x) { return $x*100;}, array($holyToT, $coldToT, $fireToT, $poisonToT, $lightningToT));
There is no syntax that allows you to do exactly this in a single statement.
You could cook up ways of doing this (by pushing everything inside an array), but the result would be much less clear and performant than a group of assignments.
Something like this comes to mind, but if they catch you doing this don't say you heard it from me:
extract(array_map(
function($i) { return $i * 100; },
compact('holyToT', 'coldToT', 'fireToT' /*, ... */ )
));
There is ni build in functionality. Depending on the PHP Version you could pass an array and a lambda function to a custom function.
function performOnAll(array $a, $fct) {
foreach($a as $v) $fct(&$a);
}
performOnAll(array($a, $b, ...), function(&$a) { $a *= 100; });
That's it basically (not syntax checked).
Related
How can I let a user (e.g. admin), by text input, choose which function to use?
I have really tried to think of a solution for this, and I really don't want to use eval, I can't even use it anyways because it is disabled (which is good), but I need the user to be able to specify what function the program needs to perform for a couple of times.
It is a general function that allows you to choose which function you want to perform, and then performs the function a lot of times.
Let me give an example that should work: (but I don't want to do this, because it uses eval, and eval is also disabled)
function generate_random_integer($a, $b) {
...
}
function rinse_and_repeat($array, $count) {
$function_name = $array[0];
$params = $array[1];
$param_string = implode(",", $params);
$query= '$function_name($param_string);';
$total = 0;
for($i = 0; $i < $count; $i++) {
$value = eval($query);
if($verbose) { print($value); }
$total += $value;
}
$ratio = $total/$count;
return($total);
}
$input = array("generate_random_integer", array(1, 10));
$total = rinse_and_repeat($input, 100);
Don't stare blind on the "generate_random_integer", I know I can do that with other functions, but I want a general solution for letting the user choose which function to perform.
How do I make something similar to this, without using eval?
Can you only do this with eval or similar functions?
If you are using OOPs, you can probably make use of strategy design pattern, which is a good practice. Using this pattern you can create object of a class based on user input
Create different class for each user input, so that you can create object of that particular class. All methods that depend on user input can go into that class.
https://refactoring.guru/design-patterns/strategy/php/example
Here's my iteration:
foreach ($this->itens as $i => $i_val) {
foreach ($i_val as $j => $j_val) {
if (is_string($this->itens[$i]->$j)) {
$this->itens[$i]->$j = iconv(mb_detect_encoding($this->itens[$i]->$j, mb_detect_order(), true), "UTF-8", $this->itens[$i]->$j);
}
}
}
This running each time something is loaded from the Database is just too performance-killer, and it's quite necessary since the previous programmers screwed the database with multiple random encodings. Anyway, is there a faster way to perform this operation in PHP? A traditional while loop is faster than a foreach? Is there a function that can apply a function to all the inner contents, like map on Python or similar?
I think http://php.net/manual/en/function.array-walk-recursive.php will do what you are after?
array_walk_recursive() is similar to array_walk(), applying your function, but does it in a multi-dimensional/recursive sense - basically it does what the name says!
As you've got a bit of logic in there, you'd have to write your own function that comprises the comparison and the resultant return value, and then pass that function to the array_walk_recursive() function (or depending on your PHP version, you could write it as an anonymous function):
$this->itens = array_walk_recursive($this->itens,function($param,$key){
if (is_string($param)) {
return iconv(mb_detect_encoding($param, mb_detect_order(), true), "UTF-8", $param);
}else{
return $param;
}
});
This a little hard for me to explain, but I'll try my best. I'm trying to find the best way to create an instance of a closure. Below is an example of how I am creating and accessing the closure:
$myvar->parse('var1, var2', function () {
//my code
});
I then loop through the strings by exploding the comma and put it into an array like so.
$array = array();
$array['var1'] = closure();
$array['var2'] = closure();
Later on in my code I use call_user_func to execute the function.
Now, the issue I'm having is that when I access $array['var1'] it calls the closure without any problem.
But when I access $array['var2'] it does nothing. I've been looking at diverse websites for a while without much luck. Do I need to use pointers (tried without success) or create a new instance of it somehow?
I currently only have access to php 5.3 on my server, so I can't use any of the awesome stuff in 5.4 :(
I'd really appreciate any feedback and advice you may have.
$yourcall = function () {
//code
};
$array['var1'] = $yourcall;
$array['var2'] = $yourcall;
Would assign the closure to those values. However:
$array['var1'] = $yourcall();
$array['var2'] = $yourcall();
As you seem to have would assign the result of calling that closure to the array items.
In your parse function (why does it take a string and not an array), I assume you want this:
function parse($string,$closure){
$array = array();
foreach(explode(',',$string) as $key) $array[$key] = $closure;
return $array;
}
Yes your question isn't clear. You knew it so I wonder why you didn't explained better.
Anyway if you need to run a closure stored inside $array['var2'] you have to specifically put in your code something like this:
$array['var2'] = function(){
//> Code
};
That's the only way
By guessing at your code, your function parse should like:
function parse($keys,$func) {
$array = array();
foreach(explode(',',$keys) as $v) {
$array[trim($v)] = $func; //> trim important here!
}
}
Most likely you have forgot to trim($v)
I'm refactoring some code that wasn't written by me. This block sets the value of $val but I want to clean it up a bit. Obviously I can't use the tertiary operator here. What other ways I can make this code cleaner?
if (isset($vars[$input])) {
$val = $vars[$input];
} elseif (isset($this->getI['io'])) {
$val = $this->getI['io'];
} elseif (isset($vars[5])) {
$val = $vars[5];
} else {
$val = 10;
}
$val = 10;
if (isset($vars[$input])) {
$val = $vars[$input];
} elseif (isset($this->getI['io'])) {
$val = $this->getI['io'];
} elseif (isset($vars[5])) {
$val = $vars[5];
}
This is about as simple as it gets without obfuscating the code. I'd rather try to simplify the logic, it's kinda hard to comprehend why the value is being looked for in so many different places.
I'm afraid I don't know php. I'm assuming that if you were to pass (say) $vars[$input] to a function, by the time it was a parameter to the function, the parameter's set-ness would be true (if that's not the case, I'd try writing a function that tested isset() on its parameter and set $val if so). I find elseif's to add complexity; I try to avoid them. In this case, I would write a function that returned the value; then all my elseif's can become plain if's.
f() {
if (isset($vars[$input])) {
return $vars[$input];
}
if (isset($this->getI['io'])) {
return $this->getI['io'];
}
if (isset($vars[5])) {
return $vars[5];
}
return 10;
}
And, of course, in your calling function, assign $val to the result of this function.
In my opinion, your example is as clean as it gets. Sure, you could write it as a huge one-liner using the ternary operator:
$val = isset($vars[$input]) ? $vars[$input] : isset($this->getI['io'] ? $this->getI['io'] : isset($vars[5]) ? $vars[5] : 10;
But this is obviously much harder to read and to maintain, so the original example is definitely cleaner (although it might be missing some comments).
I don't know...it seems to be pretty concise, as is.
If you know what it does, it does it well and it is clean enough that you can figure it out again in the future, I say don't touch it.
While you're at it figure out what it's doing and add some comments.
e.g. why assign it to the magic number 10? maybe the context of the rest of it may shed some light.
As far as code goes, you're not going to get it any simpler than this.
I have this function that I wrote that is abysmally slow since php does not handle recursion well. I am trying to convert it to a while loop, but am having trouble wrapping my head around how to do it.
Can anyone give me some tips?
public function findRoute($curLoc, $distanceSoFar, $expectedValue) {
$this->locationsVisited[$curLoc] = true;
$expectedValue += $this->locationsArray[$curLoc]*$distanceSoFar;
$at_end = true;
for($i = 1; $i < $this->numLocations; $i++) {
if($this->locationsVisited[$i] == false) {
$at_end = false;
if($expectedValue < $this->bestEV)
$this->findRoute($i, $distanceSoFar + $this->distanceArray[$curLoc][$i], $expectedValue);
}
}
$this->locationsVisited[$curLoc] = false;
if($at_end) {
if($expectedValue < $this->bestEV) {
$this->bestEV = $expectedValue;
}
}
}
I'm not going to convert your code, but you can convert a recusive function into an iterative one by creating a stack:
$stack= array();
And instead of invoking $this->findroute(), push your parameters onto this stack:
$stack[] = array($i, $distanceSoFar + $this->distanceArray[$curLoc][$i], $expectedValue);
Now surround basically everything in your function into a while loop draining the stack after having primed it:
while ($stack) {
// Do stuff you already do in your function here
You can convert a recursive function into an iterative function by using a stack to store the current state. Look into array_push() and array_pop().
At a glance I don't think recursion is your problem, yes it's slow in PHP, but It looks like your going over values more than you need to, putting the values in a stack, or several stacks and handling them, may be nice.
custom sort functions have always helped me with problems of this sort.
function sort_by_visited($x,$y)
{
return ($this->locationsVisited[$x] > $this->locationsVisited[$y]) ? -1 : 1;
}
uasort($locationsVisited,'sort_by_visited');
This will prioritize all not visited locations at the top of the stack.
This looks like your trying to find the optimal route for traversal of a series of nodes in a graph.
I'm guessing that you've not studied Computer Science as the "Travelling Salesman" problem is an archetype of Artificial Intelligence. Of course, as such, it has its own Wikipedia page:
http://en.wikipedia.org/wiki/Travelling_salesman_problem
Sorry - but just swapping from a recursive to an iterative function isn't going to make it go any faster ("php does not handle recursion well." - can you provide reference for this assertion). If you need a faster solution then you'll need to look at non-exhaustive/fuzzy methods.
C.