php check array index out of bounds - php

Consider the following array.
$a['a'] = 1;
$a['b'] = 2;
$a['c'] = 3;
$a['d'] = 4;
and then i am looping the array
foreach( $a as $q => $x )
{
# Some operations ....
if( isLastElement == false ){
#Want to do some more operation
}
}
How can i know that the current position is last or not ?
Thanks.

Take a key of last element & compare.
$last_key = end(array_keys($a));
foreach( $a as $q => $x )
{
# Some operations ....
if( $q == $last_key){
#Your last element
}
}

foreach (array_slice($a, 0, -1) as $q => $x) {
}
extraProcessing(array_slice($a, -1));
EDIT:
I guess the first array_slice is not necessary if you want to do the same processing on the last element. Actually neither is the last.
foreach ($a as $q => $x) {
}
extraProcessing($q, $x);
The last elements are still available after the loop.

You can use the end() function for this operation.

<?php
$a['a'] = 1;
$a['b'] = 2;
$a['c'] = 3;
$a['d'] = 4;
$endkey= end(array_keys($a));
foreach( $a as $q => $x )
{
# Some operations ....
if( $endkey == $q ){
#Want to do some more operation
echo 'last key = '.$q.' and value ='.$x;
}
}
?>

Related

Is there any way to compare a value at certain index with all the values to its right till it doesn't match?

Lets say I have an array :
$ar = array(0,1,0,0,0,1,0)
I want to compare the value at $ar[2], i.e. 0 with all the values to its right until stops matching.
By this. I meant that, $ar[2] == $ar[3], $ar[2] == $ar[4], and so on until it finds a mismatch, lets say at $ar[12], i.e. $ar[2] != $ar[12].
So this would tell me that $ar[2] is equal to all values to its right until $ar[12].
Now, how would I do that in the code. The array can be of any size.
My code was this :
class JumpingClouds {
public function jump() {
$ar = array(0,1,0,0,0,1,0);
for ($i=0; $i < count($ar) ; $i++) {
if ($ar[$i] == $ar[$i++]) {
if($ar[$i++] == $ar[$i+2]) {
# code...
}
} else {
# code...
}
}
}
}
$j = new JumpingClouds();
$j->jump();
But couldn't do it for a dynamic array since I want the array to be a user input in future with any size.
You can just use a while loop to loop over the elements after the one your looking at and compare it with the match value. The while also checks for the end of the array.
I've passed the array into the constructor of the class, so that the upTo() method can be called with as many values as you want on the same array (without passing it in each time).
This will return false if the from part is larger than the array...
$ar = array(0,1,0,0,0,1,0);
$from=2;
$scanner = new Scan($ar);
var_dump($scanner->upTo($from));
class Scan {
private $values;
public function __construct( array $values ) {
$this->values = $values;
}
public function upTo( int $from ) {
// Get number of elements in the array
$size = count($this->values) - 1;
// If start is past end of array, return false
if ( $from > $size ) {
return false;
}
// Store value to check against
$match = $this->values[$from];
// Loop, checking if the element looking at is the same and not the end of the array
while ( $this->values[$from] == $match && $from < $size) {
// Move onto next element
$from++;
}
// Return the position of the last element that matches
return $from;
}
}
You need to use for loop. You can use below function. It return index when the match is found otherwise returns -1
$ar = array(0,1,0,0,0,1,0);
$from = 2; //Need to match from 2 index onwards
echo $index = jump( $ar, $from );
//if -1 no match
function jump($ar, $from) {
$count = count ( $ar );
if( $from >= $count ) {
return -1;
}
$compareValue = $ar[$from];
for( $i = 0; $i < count( $ar); $i++ ) {
if( $i <= $from ) {
continue; //Index is below so continue
}
if( $ar[$i] != $compareValue ) {
return $i + 1;
}
}
return -1;
}

php more than one condition is true

There are multiple variables say $a,$b,$c,$d having boolean value.
So what i am trying to do is .
if($a){echo 1;}
if($b){echo 2;}
if($c){echo 3;}
if($d){echo 4;}
and so on.. 50 variables
is there any better way to do this?
Note: More than one variable can be true.
You can use this code to iterate :
$a= $b = $c = TRUE;
$array = array(0=> $a,1=>$b,2=> $c);
foreach($array as $key => $value){
if($value){
echo $key;
}
}
Maybe put all boolean variable inside an boolean array, and iterate the array to check the value
$boolArray = array();
$boolArray[0] = array($a, 1);
$boolArray[1] = array($b, 2);
$boolArray[2] = array($c, 3);
...
for($x = 0; $x < count($boolArray); $x++) {
if ($boolArray[x][1]) {
echo (string)$boolArray[x][2];
}
}
I think you're looking for something like this.
<?php
# Define the settings you already have
$a = true;
$b = true;
$c = true;
# Create an array with letters from a to z
# Instead of this, you can create an array of field names like array('a', 'b', 'c', 'd');
$options = range('a', 'z');
# Loop in the letters from above
foreach($options as $id => $letter) {
# Check if variable exists and boolean is true
if(isset(${$letter}) && ${$letter} === true) {
# Output number from id
echo $id + 1;
}
}
?>

PHP count the enabled value variables from an array

I have an array of values that can be DISABLED or ENABLED, so I want to know how many are there ENABLED. Here is a piece of code:
$list = array(
$variable1,
$variable2,
$variable3,
$variable4
);
$count = count($list);
Thanks for any reply.
UPDATE: the values are NOT true and or false but ENABLE / DISABLE. Do your answers apply in this case? Thanks again.
If the only valid options are boolean TRUE and FALSE, then
$countTrue = array_sum($list);
EDIT
with 'ENABLE' and 'DISABLE' as the possible values:
$countTrue = array_reduce(
$list,
function($counter, $value) {
return $counter + ($value == 'ENABLE');
},
0
);
Just use array_filter
$list = array(true,false,true,true);
$count = count(array_filter($list));
echo $count ;
Or
$list = array("Enable","DISABLE","ENabLE","ENABLE");
$count = count(array_filter($list,function($v) { return stripos($v, "enable") !== false; } ));
echo $count ;
ENABLE and DISABLE are long string but they start with E & D respectively you can use that for counting
$count = array_reduce($list,function($a,$b){$b{0} == "E" and $a++ ;return $a;},0);
echo $count ;
They Would all output
3
$array = array('ENABLED', 'DISABLED', 'ENABLED', 'ENABLED', 'ENABLED', 'DISABLED');
$count = array_count_values($array);
would produce
array(2) {
["ENABLED"]=>int(4)
["DISABLED"]=>int(2)
}
so you can call it using
$count["ENABLED"]
Just iterate through the array and count them.
$trueValues = 0;
foreach ($list as $listItem)
{
if ($listItem)
$trueValues++;
}
echo "Array has ".$trueValues." TRUE items);
$list = array('ENABLE','DISABLE','ENABLE','ENABLE');
function countTrues($n)
{
if ($n == 'ENABLE'){return $n;}
}
$x = array_filter($list , "countTrues");
$count = count($x);
This should do the trick

Determine if the array has negative numbers and change them to zero

I have wrote this code:
$final = array(
($data[0] - $data[1]),
($data[1] - $data[2]),
($data[2] - $data[3]),
($data[3] - $data[4]),
($data[4] - $data[5]),
($data[5] - $data[6])
);
Some of them will return negative numbers (-13,-42 etc...), how to change the negative ones to 0?
By the way the think i do after is:
$data_string = join(",", $final);
Example: I need to convert it like in the following:
1,3,-14,53,23,-15 => 1,3,0,53,23,0
You can map that:
$zeroed = array_map(function($v) {return max(0, $v);}, $final);
Will set all numbers lower than 0 to 0.
See array_map and max.
Additionally, you can save you some more handwriting with $data:
$final = array_reduce($data, function($v, $w)
{
static $last;
if (null !== $last) $v[] = max(0, $last - $w);
$last = $w;
return $v;
}, array());
$data_string = join(",", $final);
See array_reduce.
Edit: A foreach loop might be easier to follow, I added some comments as well:
// go through all values of data and substract them from each other,
// negative values turned into 0:
$last = NULL; // at first, we don't have a value
$final = array(); // the final array starts empty
foreach($data as $current)
{
$isFirst = $last === NULL; // is this the first value?
$notFirst = !$isFirst;
if ($notFirst)
{
$substraction = $last - $current;
$zeroed = max(0, $substraction);
$final[] = $zeroed;
}
$last = $current; // set last value
}
And here is the demo.
Am guessing this is homework. If so please mark it as such.
Hints:
use a loop instead of hardwired array references.
use an if-statement to check for negative values and switch their sign.
your use of join is correct
I like Hakre's compact answer. However, if you have a more complex requirement, you can use a function:
<?php
$data = array(11,54,25,6,234,9,1);
function getZeroResult($one, $two) {
$result = $one - $two;
$result = $result < 0 ? 0 : $result;
return $result;
}
$final = array(
getZeroResult($data[0], $data[1]),
getZeroResult($data[1], $data[2]),
getZeroResult($data[2], $data[3]),
getZeroResult($data[3], $data[4]),
getZeroResult($data[4], $data[5]),
getZeroResult($data[5], $data[6])
);
print_r($final);
?>
http://codepad.org/viGBYj4f (With an echo to show the $result before test.)
Which gives you:
Array
(
[0] => 0
[1] => 29
[2] => 19
[3] => 0
[4] => 225
[5] => 8
)
Note, you could also just return the ternary:
function getZeroResult($one, $two) {
$result = $one - $two;
return $result < 0 ? 0 : $result;
}
As well as using it in a loop:
<?php
$data = array(11,54,25,6,234,9,1);
function getZeroResult($one, $two) {
$result = $one - $two;
echo "$one - $two = $result\n";
return $result < 0 ? 0 : $result;
}
$c_data = count($data)-1;
$final = array();
for ($i = 0; $i < $c_data; $i++) {
$final[] = getZeroResult($data[$i], $data[$i+1]);
}
print_r($final);
?>
http://codepad.org/31WCbpNr

get random value from a PHP array, but make it unique

I want to select a random value from a array, but keep it unique as long as possible.
For example if I'm selecting a value 4 times from a array of 4 elements, the selected value should be random, but different every time.
If I'm selecting it 10 times from the same array of 4 elements, then obviously some values will be duplicated.
I have this right now, but I still get duplicate values, even if the loop is running 4 times:
$arr = $arr_history = ('abc', 'def', 'xyz', 'qqq');
for($i = 1; $i < 5; $i++){
if(empty($arr_history)) $arr_history = $arr;
$selected = $arr_history[array_rand($arr_history, 1)];
unset($arr_history[$selected]);
// do something with $selected here...
}
You almost have it right. The problem was the unset($arr_history[$selected]); line. The value of $selected isn't a key but in fact a value so the unset wouldn't work.
To keep it the same as what you have up there:
<?php
$arr = $arr_history = array('abc', 'def', 'xyz', 'qqq');
for ( $i = 1; $i < 10; $i++ )
{
// If the history array is empty, re-populate it.
if ( empty($arr_history) )
$arr_history = $arr;
// Select a random key.
$key = array_rand($arr_history, 1);
// Save the record in $selected.
$selected = $arr_history[$key];
// Remove the key/pair from the array.
unset($arr_history[$key]);
// Echo the selected value.
echo $selected . PHP_EOL;
}
Or an example with a few less lines:
<?php
$arr = $arr_history = array('abc', 'def', 'xyz', 'qqq');
for ( $i = 1; $i < 10; $i++ )
{
// If the history array is empty, re-populate it.
if ( empty($arr_history) )
$arr_history = $arr;
// Randomize the array.
array_rand($arr_history);
// Select the last value from the array.
$selected = array_pop($arr_history);
// Echo the selected value.
echo $selected . PHP_EOL;
}
How about shuffling the array, and popping items off.
When pop returns null, reset the array.
$orig = array(..);
$temp = $orig;
shuffle( $temp );
function getNextValue()
{
global $orig;
global $temp;
$val = array_pop( $temp );
if (is_null($val))
{
$temp = $orig;
shuffle( $temp );
$val = getNextValue();
}
return $val;
}
Of course, you'll want to encapsulate this better, and do better checking, and other such things.
http://codepad.org/sBMEsXJ1
<?php
$array = array('abc', 'def', 'xyz', 'qqq');
$numRandoms = 3;
$final = array();
$count = count($array);
if ($count >= $numRandoms) {
while (count($final) < $numRandoms) {
$random = $array[rand(0, $count - 1)];
if (!in_array($random, $final)) {
array_push($final, $random);
}
}
}
var_dump($final);
?>
Php has a native function called shuffle which you could use to randomly order the elements in the array. So what about this?
$arr = ('abc', 'def', 'xyz', 'qqq');
$random = shuffle($arr);
foreach($random as $number) {
echo $number;
}
key != value, use this:
$index = array_rand($arr_history, 1);
$selected = $arr_history[$index];
unset($arr_history[$index]);
I've done this to create a random 8 digit password for users:
$characters = array(
"A","B","C","D","E","F","G","H","J","K","L","M",
"N","P","Q","R","S","T","U","V","W","X","Y","Z",
"a","b","c","d","e","f","g","h","i","j","k","m",
"n","p","q","r","s","t","u","v","w","x","y","z",
"1","2","3","4","5","6","7","8","9");
for( $i=0;$i<=8;++$i ){
shuffle( $characters );
$new_pass .= $characters[0];
}
If you do not care about what particular values are in the array, you could try to implement a Linear Congruential Generator to generate all the values in the array.
LCG implementation
Wikipedia lists some values you can use, and the rules to select the values for the LCG algorithm, because the LCG algorith is deterministic it is guaranteed not to repeat a single value before the length of the period.
After filling the array with this unique numbers, you can simply get the numbers in the array 1 by 1 in order.
$isShowCategory = array();
for ($i=0; $i <5 ; $i++) {
$myCategory = array_rand($arrTrCategoryApp,1);
if (!in_array($myCategory, $isShowCategory)) {
$isShowCategory[] = $myCategory;
#do something
}
}
Easy and clean:
$colors = array('blue', 'green', 'orange');
$history = $colors;
function getColor($colors, &$history){
if(count($history)==0)
$history = $colors;
return array_pop( $history );
}
echo getColor($colors, $history);

Categories