Currently my mind is under heavy pressure and I can't stay a long time focusing on one single issue, I am pretty sure that the way I made it is basic and can be improved to make it smaller and easier (more professional maybe ?) code;
<?php
$intro_id = rand(1,2);
if($intro_id == 1 && !empty($options['hidden_intro_one'])){
$hidden_intro = $options['hidden_intro_one'];
}
elseif(!empty($options['hidden_intro_two'])){
$hidden_intro = $options['hidden_intro_two'];
}
else{
//back to circle number 1
$hidden_intro = $options['hidden_intro_one'];
}
?>
Partially SOLVED :
the solution was to use array_rand() function like this :
<?php
$random_intro = array($options['hidden_intro_one'],$options['hidden_intro_two']);
$hidden_intro = $random_intro[array_rand($random_intro)];
?>
But if one of the intros is left empty, it will appear empty when you echo the code, while I want to print the other intro (if not empty) instead...
It can certainly be 'improved'. Code can always be improved :) One easy improvement you can always do (more of a habit to teach yourself) is to add a comment about what the code is supposed to do.
Anyway, what (I think) you're trying to do is basically the same as:
$hidden_intro = $options[ array_rand( $options ) ];
<?php
$intros = array(
1 => $options['hidden_intro_one'],
2 => $options['hidden_intro_two']
);
$intro_id = rand(1,2);
$hidden_intro = empty($intros[$intro_id]) ? reset($intros) : $intros[$intro_id];
?>
Although I don't like using reset() as a way to get the first possible value, but you can customize the 'default' value process :)
Something like this maybe:
$intro = array("hidden_intro_one","hidden_intro_two");
$hidden_intro = $options[array_rand($intro)];
Or, if $options only contains hidden_intro_one and hidden_intro_two you could just do:
$hidden_intro = array_rand($options);
EDIT oops, this leaves out the part where it can't be empty.
If $options only contains hidden_intro_one and hidden_intro_two
$hidden_intro = $options["hidden_intro_one"]; // fallback if both are empty
shuffle($options);
foreach($options as $option)
if(!empty($option)){
$hidden_intro = $option;
break;
}
Else
$hidden_intro = $options["hidden_intro_one"]; // fallback if both are empty
$intros = array("hidden_intro_one","hidden_intro_two");
shuffle($intros);
foreach($intros as $intro)
if(!empty($options[$intro])){
$hidden_intro = $options[$intro];
break;
}
This might not necessarily be better though, but it will be if you add more values.
Encapsulate what varies and for the standard problem use an existing function like array_rand:
$intros = get_non_empty_intros_from_options($options);
$hidden_intro = array_rand($intros);
function get_non_empty_intros_from_options($options)
{
$intro_option_keys = array('one', 'two');
$intro_option_key_mask = 'hidden_intro_%s';
$intros = array();
foreach ($intro_option_keys as $intro)
{
$key = sprintf($intro_option_key_mask, $intro);
if (empty($options[$key]))
continue
;
$intros[$key] = $options[$key];
}
return $intros;
}
This method will allow you to use more than one intro.
<?php
//why not make your intro's an array in your options array
$options['hidden_intro'] = array('one', 'two');
//declare your intro variable
$hidden_intro;
//now lets loop our intro's
foreach($options['hidden_intro'] as $intro)
{
if(!empty($intro))
{
$hidden_intro = $into;
break;
}
}
if(isset($hidden_intro))
{
//use your intro here
}
?>
Just for fun, an (almost) oneliner:
$to_be_choosen_keys = array("hidden_intro_one","hidden_intro_two");
$hidden_intro = array_rand(
array_intersect_key(
$options,
array_flip($to_be_choosen_keys)
)
);
Related
I have loop value with code
foreach($season as $seasons){
echo $seasons->Combined_season ;
}
and the result is 0000000011111111111111111111111222222222222222222222223333333333333333333333344444444444444444444444555555555
How to skip if there same values?
I want the result is
012345
You are looking for "unique" values:
<?php
foreach($season as $seasons){
$result[] = $seasons->Combined_season;
}
echo implode('', array_unique($result));
A somewhat awkward but more memory efficient version would be this:
<?php
foreach($season as $seasons){
$result[$seasons->Combined_season] = $seasons->Combined_season;
}
echo implode('', $result);
And the most efficient variant:
<?php
foreach($season as $seasons){
$result[$seasons->Combined_season] = null;
}
echo implode('', array_keys($result));
All approaches have the advantage that they do not require a conditional in each loop iteration which makes them far more efficient for bigger input sets.
Here an update to answer your additional question:
I mentioned more than once in my comments that the variant 2 and 3 deliver what you are looking for. That you only have to use the values internally instead of imploding them for output.
The following is exactly the third approach from above, the only difference is that I did what I told you before in the comments: use the values instead of imploding them. As far as I can see it delivers exactly what you are looking for:
<?php
foreach($season as $seasons){
$result[$seasons->Combined_season] = null;
}
$value = array_keys($result);
$printedSeasons = [];
foreach($season as $seasons){
if (!in_array($seasons->Combined_season, $printedSeasons)) {
$printedSeasons[] = $seasons->Combined_season;
echo $seasons->Combined_season;
}
}
<?php
$values = [];
foreach($season as $seasons){
if(! in_array($seasons->Combined_season, $values)) {
$values[] = $seasons->Combined_season;
echo $seasons->Combined_season ;
}
}
basically, you store any new value in an array, and before printing a value, you check if it already is in that array.
Using the "array approach" is maybe the best approach. But if your results are sorted like in your example you could use an other approach, with a current value.
$curr_val = '';
foreach($season as $seasons){
if ($seasons->Combined_season != $curr_val){
echo $seasons->Combined_season ;
$curr_val = $seasons->Combined_season ;
}
}
You can use an external variable:
$old_value = '';
foreach($season as $seasons){
$new_value = $seasons->Combined_season;
if($old_value != $new_value)
{
echo $new_value;
$old_value = $new_value;
}
}
I have code like this:
$finalResult = true;
$finalResult = $finalResult && function_01();
// some code here
$finalResult = $finalResult && function_02();
// some many lines of code here
$finalResult = $finalResult && function_XX();
And I'm looking for a way how to shorten the code (just for a human-readibility reasons) to something like:
$finalResult = true;
$finalResult &&= function_01();
// some code here
$finalResult &&= function_02();
// some many lines of code here
$finalResult &&= function_XX();
But of course this doesn't work and operator &= is not for boolean values, but for binary.
How should I do this ?
Thanks.
$names = array('function01','function02'...);
$result = true;
foreach($names as $caller)
{
$result = $result && $caller();
}
otherwise instead of $caller() you could look for call_user_func ( http://us3.php.net/call_user_func )
it's not really fantastic, but it's shorter :/ not a big deal
edit:
uhm... i guess that after your edit this solution is not more functional... should i delete it ?
I would also reconsider the logic of your code by adding a class that makes these checks: if all the checking logic is in a class whose purpose is just that you could surely benefit of readability
Stormsson's but improved - finish as soon as you know the result:
$names = array( 'function01','function02'... );
$result = true;
foreach( $names as $caller )
{
if ( $result == false ) break; // short circuit
$ret = $caller()
if ( $ret == false )
{
$result = false;
break; // short circuit
}
$result = $result && $ret;
}
OK, after all it seems I will not get it any simpler than original.
For those of you who don't understand why I want to have it in some "short" form - only reason was to have it shorter and nicer. Just the same reason why there is possibility to write $a += 3 just for beauty.
Anyway, thanks to everybody :)
Alright I'm working with a large multidimensional array which has more information in it than I need and I want to loop through it to filter the data which I'm interested in. Sadly this multidimensional array is produced dynamically and doesn't always contain the data I want, so I have to use logic like:
if(isset($ar['b']['ba']['baa'])){
echo '<h3>'.$ar['b']['ba']['baa'].'</h3>';
}
if(isset($ar['b']['ba']['baba'])){
echo '<h3>'.$ar['b']['ba']['baba'].'</h3>';
}
if(isset($ar['b']['ba']['babb'])){
echo '<h3>'.$ar['b']['ba']['babb'].'</h3>';
}
The above works great but its a bit messy-looking so I converted the above to:
$refAr=array();
$refAr[]='b->ba->baa';//3
$refAr[]='b->ba->bab->baba';//4
$refAr[]='b->ba->bab->babb';//5
The above looks a lot more nice and neat and is how I want to control the script in case I need to reference different keys in the future. The problem I am having is trying to use the above format to actually reference the array. I thought variable variables would work but apparently it fails. My second attempt using eval worked but I'm not very happy with my solution. This is where I need you guys to come in, is there a better way to do this? Here's my attempt below:
<?php
$ar=array(
'a'=>array('aa'=>1,'ab'=>2),
'b'=>array(
'ba'=>array('baa'=>3,'bab'=>array('baba'=>4,'babb'=>5),'bac'=>array('baca'=>6,'bacb'=>7)),
)
);
$refAr=array();
$refAr[]='b->ba->baa';//3
$refAr[]='b->ba->bab->baba';//4
$refAr[]='b->ba->bab->babb';//5
foreach($refAr as $ref)
{
$r=explode('->',$ref);
$r="\$ar['".implode("']['",$r)."']";
echo '<h1>'.$r.'</h1>';
echo '<h3>'.$$r.'</h3>';//undefined
eval('$t='.$r.';');
echo "<h3>$t</h3>";//works but uses eval, is there a better way?
}
You can try
$ar = array();
$ar['b']['ba']['baa'] = 3;
$ar['b']['ba']['bab']['baba'] = 4;
$ar['b']['ba']['bab']['babb'] = 5;
$refAr = array();
$refAr[] = 'b->ba->baa'; // 3
$refAr[] = 'b->ba->bab->baba'; // 4
$refAr[] = 'b->ba->bab->babb'; // 5
foreach ( $refAr as $ref ) {
$t = $ar;
foreach ( explode("->", $ref) as $v ) {
if (!isset($t[$v]))
break;
$t = $t[$v];
}
is_array($t) and $t = null;
echo "<h3>$t</h3>";
}
Output
345
I decided to answer my own question. This is what I wound up using:
<?php
//Sample PHP representation of dynamically-pulled JSON data from an untrusted source
$ar=array(
'a'=>array('aa'=>1,'ab'=>2),
'b'=>array(
'ba'=>array('baa'=>3,'bab'=>array('baba'=>4,'babb'=>5),'bac'=>array('baca'=>6,'bacb'=>7)),
)
);
//Reusable function
function resolveReference($ar,&$ref)
{
$t = $ar;
foreach ( explode('->',$ref) as $v )
{
if (!array_key_exists($v,$t)){$ref=null;return false;}
$t = $t[$v];
}
$ref=$t;
return true;
}
//The references I'm interested in but don't know if my dynamic data will contain these keys every time
$refAr=array();
$refAr[]='b->ba->baa';
$refAr[]='b->ba->bab->baba';
$refAr[]='b->ba->bab->babb';
$refAr[]='b->doesnt->exist';
foreach($refAr as $ref)
{
echo '<h1>'.$ref.'</h1>';
if(resolveReference($ar,$ref))
{
echo '<h3><span style="color:blue;">'.$ref.'</span></h3>';
}else{
echo '<h3><span style="color:red;">Alternative text for non-existent expected reference</span></h3>';
}
}
So, as the title says... any alternative to:
$valid_times = array('ever', 'today', 'week', 'month');
if (($this->_time == 'ever') OR ($this->_time == 'day'))
OR
if (in_array($this->_time, $valid_times))
??
Note: I know the mentioned above works, but I'm just looking for new things to learn and experiment with
UPDATE
Thanks for the info, but I didn't mentioned switch() as an alternative because it's not the case for my code. It has to be an if-statement, and I was wondering if exists something like:
if($this->_time == (('ever') OR ('day') OR ('month')))
What do you think? That would be a shorter way of the first if mentioned above
What about ?
$a1 = array("one","two","three");
$found = "two";
$notFound = "four";
if (count(array_diff($a1,array($found))) != count($a1))
/* Found */
Either you can use
$found = array("one","three");
if (count(array_diff($a1,$found)) != count($a1));
/* Either one OR three */
http://codepad.org/FvXueJkE
The only alternative I can think to accomplish this would be using regex.
$valid_times = array('ever','day','week','hour');
if(preg_match('/' . implode('|', $valid_times) . '/i', $this->_time)){
// match found
} else {
// match not found
}
[EDIT] Removed original answer since you've now specified you don't want to use switch.
In your updated question, you asked if something like this is possible:
if($this->_time == (('ever') OR ('day') OR ('month')))
The direct answer is 'no, not in PHP'. The closest you'll get is in_array(), with the array values in place in the same line of code:
if(in_array($this->_time, array('ever','day','month'))
PHP 5.4 has an update allows for shorter array syntax, which means you can drop the word array, which makes it slightly more readable:
if(in_array($this->_time, ['ever','day','month'])
But it is still an in_array() call. You can't get around that.
Sometime like this for in_array?
$arr = array(1, 2, 'test');
$myVar = 2;
function my_in_array($val, $arr){
foreach($arr as $arrVal){
if($arrVal == $val){
return true;
}
}
return false;
}
if(my_in_array($myVar, $arr)){
echo 'Found!';
}
Convoluted, but it is an alternative
$input = 'day';
$validValues = array('ever','day');
$result = array_reduce($validValues,
function($retVal,$testValue) use($input) {
return $retVal || ($testValue == $input);
},
FALSE
);
var_dump($result);
You could also use the switch statement.
switch ($this->_time) {
case 'ever':
case 'day':
//code
break;
default:
//something else
}
For the sake of science, it turns out you can use yield in a ternary operator, so you could put some complex evaluations in a anonymous generator, and have it yield on the first one that evaluates to true, without needing to evaluate them all:
$time = 'today';
if( (function()use($time){
$time == 'ever' ? yield true:null;
$time == 'today' ? yield true:null;
$time == 't'.'o'.'d'.'a'.'y' ? yield true:null;
})()->current() ){
echo 'valid';
}
In this case it will echo 'valid' without ever evaluating the concatenation.
if ($_POST['op_ep_cat'] == 'op_single_ep')
{
$ep_place = $_POST['the_place'];
$eps_array = array();
array_push($eps_array, $ep_place);
}
else if ($_POST['op_ep_cat'] == 'op_category') {
$cat_site = $_POST['the_place'];
$taken_cat_site = file_get_contents($cat_site);
if (preg_match_all('#<div class="content_ep"><a href="(.+?)"#si', $taken_cat_site, $eps_array));
else if (preg_match_all('#<div class="postlist">\s*<a href="(.+?)"#si', $taken_cat_site, $eps_array));
}
foreach(array_reverse($eps_array[1]) as $eps_match)
{
echo 'Arughh!';
}
The above works for the 'op_category' perfectly, but not for the 'op_single_ep'... So basically $ep_place needs to be apart of the $eps_array[1], if possible, somehow.. Hopefully any of this makes sense!
I appreciate any help!
try that
$eps_array = array(1 => array($_POST['the_place']));
but whole code is just weird
$eps_array[1] is not array, is element of $eps_array
You can make array
$eps_array = array(1=>array());
array_push($eps_array[1], $ep_place);
Try to read manual about What is array
it'd be $eps_array[0] for the op_single_ep version. Remember, PHP arrays have 0-based indexes.
Try this
if ($_POST['op_ep_cat'] == 'op_single_ep')
{
$ep_place = $_POST['the_place'];
$eps_array = array();
$eps_array[1] = array();
array_push($eps_array[1], $ep_place);
}