I have the following code which works perfectly fine to give me the name of the customer with the ID of 10:
foreach($customer_list as $row) {
if ($row->CUSTOMER_ID == 10)
echo $row->NAME;
}
Is there a way I can do this more directly, without the foreach loop and if statement? I'd like to do something like:
echo $customer_list[CUSTOMER_ID][10]->NAME;
But I don't know the syntax or if it's even possible.
You could use array_filter It will return an array of customers whose ID is 10. We then select the first match (the only match probably) and access the NAME property.
$name = reset( array_filter(
$customer_list,function($c){return $c->CUSTOMER_ID === 10;}
))->NAME;
The cleaner approach is to factor it out, into a separate function:
$getCustName = function($list,$id){
return reset( array_filter(
$list,
function($c) use ($id) {return $c->CUSTOMER_ID === $id;}
))->NAME;
};
Then you can get the name easily with just one line:
$name = $getCustName($customer_list,10);
You can use php array_filter method.
Basically you need to pass a function which will check value of customer_Id and returns the element of the array.
you can add your code inside a function and then call that function when you need the name. I am assuming you have unique customer ID's.
function getCustName($customers,$id){
if(count($customers)>0){
foreach($customers as $row) {
if ($row->CUSTOMER_ID == $id)
return $row->NAME;
}
} else{
return false;
}
}
Now if you need to get customer name just call the function
echo getCustName($customer_list,10);
Related
I have an array with multiple keys and I want to be sure they're all in the format I want. For example, if they're all ISO Alpha-2 country codes, I created one function returning true or false to test it.
Basically, I would like to replace this foreach by only one line:
$countriesList = ['US', 'FR', 'CA'];
$correct = true;
foreach ($countriesList as $iso2) {
if (!$this->isIso2($iso2)) {
$correct = false;
}
}
If you really want to replace the foreach with a single call you can use array_walk as follows:
$countriesList = ['US', 'FR', 'CA'];
$correct = true;
array_walk( $countriesList, function( $country ) use (&$correct) { $correct = $correct && $this->isIso2( $country ); } );
The statement use (&$correct) lets the inline callback access the $correct variable (that otherwise would be out of the callback scope).
Note:
you don't have a problem in your original code.
It's readable, concise and I don't see any evident performace flaw.
I would just add a break; to terminate the loop the first time a "false case" is found. There is no reason to keep iterating:
if (!$this->isIso2($iso2)) {
$correct = false;
break; // <--- EXIT THE LOOP
}
In production I would definitely stick with the foreach approach.
Anyway as a programming exercise the solution at the beginning of my answer reduces the loop at a single call.
array_walk iterates over all the items of an array. For each item the inline callback function is invoked with the current item passed as first parameter.
When dealing with arrays I am forced to add a bunch of repetitive code to handle arrays with one child versus multiple:
//If more than one step, process each step, elcse processs single
if(!array_key_exists('command',$pullcase['steps']['step'])) {
foreach($pullcase['steps']['step'] as $step) {
$command=$step['command'];
$parameter=$step['parameter'];
if(isset($step['value'])){
$value = $step['value'];
$this->runCommands($command,$parameter,$value);
} else {
$this->runCommands($command,$parameter);
}
}
} else {
$command = $pullcase['steps']['step']['command'];
$parameter = $pullcase['steps']['step']['parameter'];
if(isset($pullcase['steps']['step']['value'])){
$value = $pullcase['steps']['step']['value'];
$this->runCommands($command,$parameter,$value);
}
else { $this->runCommands($command,$parameter); }
}
As you can see, I'm having to duplicate my efforts depending on if there is a single item in an array versus multiple:
$pullcase['steps']['step'][0]['command']
vs
$pullcase['steps']['step']['command']
How can I simplify this code so that I can use a single variable for all instances?
If you control the creation of the array, make step an array of one even if there is only one so you always have an array. Is that possible?
You either have a step array [step][0][command] or you have a single step [step][command]. So when you create the array instead of [step][command] make it [step][0][command] etc. Standard way of doing it, problem solved as you only need the foreach.
If you can't do it at array creation then consider doing it before the loop:
if(is_array($pullcase['steps']['step'])) {
$steps = $pullcase['steps']['step'];
} else {
$steps[] = $pullcase['steps']['step'];
}
foreach($steps as $step) {
$value = isset($step['value']) ? $step['value'] : null;
$this->runCommands($step['command'], $step['parameter'], $value);
}
Also, if runCommands() can detect a empty argument, then an alternative to the if/else for the function call is used above.
The following may help. It doesn't do much but call the function "runcommands" on a value if the key is 'command'. I am using it to show how you can use array_walk_recursive to possibly solve your problem.
First, you need the function to use:
function runcommandswhencommand($value, $key)
{
if($key == 'command') runcommands($value);
}
Now, you can use the recursive walk on your array:
array_walk_recursive($pullcase, 'runcommandswhencommand');
With this, whenever the key is 'command', the value of that index will be used in the parameter of the function runcommands().
I'm curious if I can assign a variable the value of a specific array index value returned by a function in PHP on one line.
Right now I have a function that returns an associative array and I do what I want in two lines.
$var = myFunction($param1, $param2);
$var = $var['specificIndex'];
without adding a parameter that determines what the return type is, is there a way to do this in one line?
In PHP 5.4, you can do this: $var = myFunction(param1, param2)['specificIndex'];.
Another option is to know the order of the array, and use list(). Note that list only works with numeric arrays.
For example:
function myFunction($a, $b){
// CODE
return array(12, 16);
}
list(,$b) = myFunction(1,2); // $b is now 16
You could add an additional optional parameter and, if set, would return that value. See the following code:
function myFunction($param1, $param2, $returnVal = "")
{
$arr = array();
// your code here
if ($returnVal)
{
return $arr[$returnval];
}
else
{
return $arr;
}
}
I have a table that consists of comments. Some of them are replies to other comments and have a value set in parent_commentid table. I'm trying to create a function that checks each element in a result set if there is a value in the parent_columnid and if so take the entire element and sort it inside the element with a comment_id that matches the parent_commentid of the current element in the iteration. This is what I've come up with so far.
function sort_comments($comments){
$result = array();
foreach($comments as $comment){
if(is_null($comment['parent_commentid'])) $result[] = $comment;
else{
$parent_comment = array_search($comment['parent_commentid'], $comments);
if($parent_array !== false) $result[$parent_comment][] = $comment;
}
}
}
array_search is not the function I'm looking for but is the closets thing I could think of. Im not sure where to go from here. Keep in mind also that there can exist replies to other replies.
You need to store the comments by their own id, so that you can reference them later:
function sort_comments($comments){
$result = array();
foreach($comments as $comment){
if(is_null($comment['parent_commentid'])){
$result[$comment['commentid']] = $comment;
}else{
$parent_comment = $result[$comment['parent_commentid']]
if($parent_comment)
$parent_comment[$comment['commentid']] = $comment;
else
// what happens in this case:
// parent_commentid set, but no such comment exists?
}
}
Note the $comment['commentid']. I don't know how you call the id of a comment (commentid ?), but since you have a column parent_commandid you most likely do have such a column to reference your comments. Use that to store the comments, on top level or inside other comments.
To sort by internal fields of an array I usually use usort. Usort works as a recursive method so you can ensure that everytime you try to sort an element inside an array you will call your custom function. In this way you will get a more clean code.
Here is an example:
function cmp_rand_score($a, $b)
{
if($a["rand_score"] == $b["rand_score"]){
return 0;
}
return ($a["rand_score"] < $b["rand_score"]) ? 1 : -1;
}
//If you are inside a class:
usort($rows, array($this, "cmp_rand_score"));
//If not you can call directly:
usort($rows, "cmp_rand_score");
Hope it helps.
Here's my code:
$quizId = '';
foreach ($module['QuizListing'] as $quizListing) {
if ($quizListing['id']) {
$quizId = $quizListing['id'];
break;
}
}
Is there a better way of doing this?
What you're doing is reasonable assuming that:
multiple quiz listings appear; and
not all of them have an ID.
I assume from your question that one of both of these is not true. If you want the first quiz listing then do this:
$listing = reset($module['quizListing']);
$quizId = $listing['id'];
The reset() function returns the first element in the array (or false if there isn't one).
This assumes every quiz listing has an ID. If that's not the case then you can't get much better than what you're doing.
Slight change:
$quizId = '';
foreach ($module['QuizListing'] as $quizListing) {
if (isset($quizListing['id'])) {
$quizId = $quizListing['id'];
break;
}
}
to answer if this array is coming from a database you probably have to better to filter your query not to include those row at first place
something like
SELECT * from Quiz WHERE id <> 0
this would give you an array usable without any other processing.
$quiz = array_shift($module['QuizListing']);
if (null != $quiz) {
echo "let's go";
}
Using array_key_exists you can check if the key exists for your array. If it exists, then assign it to whatever you want.
if (array_key_exists('id', $quizListing)) {
$quizId = $quizListing['id'];
}