I have a foreach in which I have three different arrays. I want to put the value - when running the foreach - in the different arrays every third time (look example below for better explanation).
Ex: arr = blue, red, green, yellow, brown
arr1 = blue, yellow arr2 = red, brown arr3 = green
I have this code (but dont work because the modulus doesn't come down to the last if statement more then the first execution of the if).
$count = 0;
foreach($values as $value){
if($count%2){
$arrSecond[] = $value[img][url];
}
else if($count%3){
$arrThird[] = $value[img][url];
}
else {
$arrFirst[] = $value[img][url];
}
$count++;
}
How can I solve this?
You need to be using modulus 3 the whole time only with different offsets:
foreach($values as $value){
$mod = $count%3;
if($mod == 1){
$arrSecond[] = $value['img']['url'];
}
// elseif, not else if!
elseif($mod == 2){
$arrThird[] = $value['img']['url'];
}
else {
$arrFirst[] = $value['img']['url'];
}
$count++;
}
Or you could simply make a single array:
$count = 0;
$data = array();
foreach($source as $value) {
$data[$count % 3][] = $value[img][url];
$count++;
}
That gives you 3 sub arrays with the $value stuff spread out evening within them.
what you can do is the following:
$count = 0;
foreach($values as $value){
switch($count){
case 0:
$arrFirst[] = $value[img][url];
$count = 1;
break;
case 1:
$arrSecond[] = $value[img][url];
$count = 2;
break;
case 2:
$arrThird[] = $value[img][url];
$count = 0;
break;
}
}
This is basically a 3 state state machine which should be more efficient than using modulus for a large number of images.
Related
I need to find the min and max position into an array where some value exist!
use a loop inside a loop to compare values is not an option ( my array has 100.000 values )
e.g=
$myarray[0]="red";
$myarray[1]="red";
$myarray[2]="blue";
$myarray[3]="blue";
$myarray[4]="blue";
$myarray[5]="red";
how to get the min and max position where blue exist?
Use the second argument for array_keys:
if($blue = array_keys($myarray, 'blue')) {
$min = min($blue);
$max = max($blue);
}
may be this is the answer?
function getMinKey($arr, $search){
if(!in_array($search, $arr)){
return false;
}
foreach($arr as $key => $value){
if($value == $search){
return $key;
}
}
}
function getMaxKey($arr, $search){
if(!in_array($search, $arr)){
return false;
}
$arrCount = count($arr)-1;
for($i = $arrCount; $i >=0; $i--){
if($arr[$i] == $search){
return $i;
}
}
}
All solutions, so far, have searched the whole array, which might be quite inefficient. You only need to search from the start upto the first "blue" and from the end downto the last "blue". Like this:
$find = "blue";
$first = false;
$last = false;
$max = count($myarray);
$key = 0;
while ($key < $max) {
if ($myarray[$key] == $find) {
$first = $key;
break;
}
$key++;
}
if ($first !== false) {
$key = --$max;
while ($key > 0) {
if ($myarray[$key] == $find) {
$last = $key;
break;
}
$key--;
}
}
Note that this code takes into account that nothing will be found. In that case $first and $last will contain false. It also checks to see if the $first was found to prevent searching through the array twice when there's clearly no need for that.
You can use array_keys with the search_value to extract all the matching keys, and then max and min to get the two ones that you want.
$keys = array_keys($myarray,'blue'); //[2,3,4]
$maxKey = max($keys); //4
$minKey = min($keys); //2
I have to advise that performance wise is better to do a for loop:
$length = count($myarray);
$minKey = FALSE;
$maxKey = FALSE;
$search = 'blue';
for($i=0;$i<$length;$i++){
if($myarray[$i] == $search){
if($minKey === FALSE) $minKey = $i;
$maxKey = $i;
}
}
I have array with variables from $qA01_1 up to $qA30_5 (150 variables). Some of the variables can have value 0 or 1 or 5 (example $qA21_3 = 0 or 1 or 5). And I would like to know how to make sum of all variables which have value 1.
Here part of array
$qA01_1 = $_SESSION['qA01_1']; // example: $qA01_01 can have value 0 or 1 or 5, like other variables
$qA01_2 = $_SESSION['qA01_2']; // $qA01_02 = 0 or 1 or 5
$qA01_3 = $_SESSION['qA01_3']; // $qA01_03 = 0 or 1 or 5
$qA01_4 = $_SESSION['qA01_4']; // $qA01_04 = 0 or 1 or 5
$qA01_5 = $_SESSION['qA01_5']; // $qA01_05 = 0 or 1 or 5
$qA02_1 = $_SESSION['qA02_1']; // $qA02_01 = 0 or 1 or 5
$qA02_2 = $_SESSION['qA02_2']; // $qA02_02 = 0 or 1 or 5
$qA02_3 = $_SESSION['qA02_3']; // $qA02_03 = 0 or 1 or 5
$qA02_4 = $_SESSION['qA02_4']; // $qA02_04 = 0 or 1 or 5
$qA02_5 = $_SESSION['qA02_5']; // $qA02_05 = 0 or 1 or 5
// up to...
$qA30_1 = $_SESSION['qA30_1']; // $qA30_01 = 0 or 1 or 5
$qA30_2 = $_SESSION['qA30_2']; // $qA30_02 = 0 or 1 or 5
$qA30_3 = $_SESSION['qA30_3']; // $qA30_03 = 0 or 1 or 5
$qA30_4 = $_SESSION['qA30_4']; // $qA30_04 = 0 or 1 or 5
$qA30_5 = $_SESSION['qA30_5']; // $qA30_05 = 0 or 1 or 5
Here is proposal but not work. I´m begginer, please for help.
$values = [];
for($i=1;$i<=30;$i++)
{
foreach([1,2,3,4,5] as $index)
{
if(${'qA'.str_pad($i, 2, "0", STR_PAD_LEFT).'_'.$index} == 1)
{
$values[] = ${'qA'.str_pad($i, 2, "0", STR_PAD_LEFT).'_'.$index};
}
}
}
echo $values;
Just loop through the $_SESSION array:
// This is where we'll hold all the saved numbers
// from values ending with _1
$array_of_numbers = [];
// Loop through each session
foreach ( $_SESSION as $key => $val )
{
// Only save the keys that match and equal 1
if ( preg_match('/^qA\d{2}?_\d$/', $key, $matches) && $val == 1 )
{
$array_of_numbers[] = $val;
}
}
// Sum the numbers that we gathered
$sum_of_array = array_sum($array_of_numbers);
If you just want a sum, you don't need the $values array. Just add the value to a $sum variable.
$sum = 0;
for($i=1;$i<=30;$i++)
{
foreach([1,2,3,4,5] as $index)
{
$var = 'qA'.str_pad($i, 2, "0", STR_PAD_LEFT).'_'.$index
if(${$var} == 1)
{
$sum += ${$var};
}
}
}
echo $sum;
BTW, you can't echo an array. If you want to see the contents of an array, use var_dump($values); or print_r($values);
Time for a rethink. No reason to unpack the array like you are doing.
Lets put the $_SESSION values that we are interested in into a new array and work with that. (not necessary to put in to a new array, I just prefer to not work with the super global variables more than necessary)
//Create new array
$myArray = [];
foreach( $_SESSION as $key=>$val ){
if( preg_match('/qA\d{2}_[1-5]/', $key) ){
$myArray[$key] = $val;
}
}
$sum = 0;
foreach( $myArray as $key=>$val ){
if( preg_match('/qA\d{2}_1/', $key) ){
$sum += $val;
}
}
var_dump($sum);
Since the logic here is a bit confusing, I think separating it out into a couple "self-documenting" functions would be better practice. Something like this should work:
$sum = 0;
for ($i = 1; $i <= 30; $i++) {
for ($j = 1; $j <= 5; $j++) {
$qa_index = qa_index($i, $j);
if ($_SESSION[$qa_index] == 1)
$sum++; // no need to _actually_ sum since it's just 1
}
}
function qa_index($major, $minor) {
return 'qA'.left_pad_zeros($major).'_'.$minor."\n";
}
function left_pad_zeros($val, $pad_amount = 2) {
return str_pad($val, $pad_amount, '0', STR_PAD_LEFT);
}
EDIT: I imagine some people might think functions are unnecessary overhead here. And that may be IF whatever application is using this NEEDS to squeeze out every little bit of performance improvement they can. However, if that's not the case, I think this is much better practice as it is much easier to read and maintain.
$TotalVal = 0;
for($i=1; $i<=5; $i++){
for($j=1; $j<=5; $j++){
If($i<10){
$StrVar = 'qA0'.$j.'_'.$i.'[0]'; // considering ur using array if not remove [0].
If ($$StrVar == 1)
$TotalVal = $TotalVal + $$StrVar;
}else{
$StrVar = 'qA'.$j.'_'.$i.'[0]';
If ($$StrVar == 1)
$TotalVal = $TotalVal + $$StrVar;
}
}
}
echo $TotalVal;
This will give you sum of all values which is having 1 if u need 5 change in if condition
I would like to Convert simple string to another format based on below logic
Example 1 : if string is 3,4-8-7,5 then I need the set as (3,8,7),(4,8,5).
Example 2: If string is "4-5,6-4" then required set will be (4,5,4),(4,6,4).
More Clear Requirements:
if string is 5-6,7,8-2,3-1. It need to be divided first like [5] AND [(6) OR (7) OR (8)] AND [(2) OR (3)] AND [1]. Result must be All possible combination: (5,6,2,1),(5,6,3,1),(5,7,2,1),(5,7,3,1),(5,8,2,1),(5,8,3,1).
The Logic behind to building the set are we need to consider ',' as OR condition and '-' as AND condition.
I am trying my best using For loop but unable to find solution
$intermediate = array();
$arry_A = explode('-', '3,4-8-7,5');
for ($i = 0; $i < count($arry_A); $i++) {
$arry_B = explode(',', $arry_A[$i]);
for ($j = 0; $j < count($arry_B); $j++) {
if (count($intermediate) > 0) {
for ($k = 0; $k < count($intermediate); $k++) {
$intermediate[$k] = $intermediate[$k] . ',' . $arry_B[$j];
}
} elseif (count($intermediate) === 0) {
$intermediate[0] = $arry_B[$j];
}
}
}
echo $intermediate, should give final result.
Cool little exercise!
I would do it with the following code, which I will split up for readability:
I used an array as output, since it's easier to check than a string.
First, we initialize the $string and create the output array $solutions. We will calculate the maximum of possible combinations from the beginning ($results) and fill the $solutions array with empty arrays which will be filled later with the actual combinations.
$string = '3,4-8-7,5';
$solutions = array();
$results = substr_count($string,',')*2;
for($i = 0; $i < $results; $i++) {
array_push($solutions,array());
}
We will need two helper functions: checkSolutions which makes sure, that the combination does not yet exist more than $limit times. And numberOfORAfterwards which will calculate the position of an OR pattern in the $string so we can calculate how often a combination is allowed in the single steps of the walkthrough.
function checkSolutions($array,$solutions,$limit) {
$count = 0;
foreach($solutions as $solution) {
if($solution === $array) $count++;
}
if($count < $limit) return true;
else return false;
}
function numberOfORAfterwards($part,$parts) {
foreach($parts as $currPart) {
if($currPart === $part) $count = 0;
if(isset($count)) if(!ctype_digit($currPart)) $count++;
}
return $count;
}
Now the main part: We are going to loop over the "parts" of the $string a part are the digits between AND operations.
If you need further explanation on this loop, just leave a comment.
$length = 0;
// split by all AND operations
$parts = explode('-',$string);
foreach($parts as $part) {
if(ctype_digit($part)) {
// case AND x AND
foreach($solutions as &$solution) {
array_push($solution,$part);
}
} else {
// case x OR x ...
$digits = explode(',',$part);
foreach($digits as $digit) {
for($i = 0; $i < $results/count($digits); $i++) {
foreach($solutions as &$solution) {
if(count($solution) == $length) {
$test = $solution;
array_push($test,$digit);
$limit = numberOfORAfterwards($part,$parts);
echo $digit.' '.$limit.'<br>';
if(checkSolutions($test,$solutions,$limit)) {
array_push($solution,$digit);
break;
}
}
}
}
}
}
$length++;
}
print_r($solutions);
Some tests:
String: 3,4-8-7,5
Combinations: (3,8,7)(3,8,5)(4,8,7)(4,8,7)
String: 5-6,7,8-2,3-1
Combinations: (5,6,2,1)(5,6,3,1)(5,7,2,1)(5,7,3,1)(5,8,2,1)(5,8,2,1)
String: 2,1-4-3,2-7,8-9
Combinations: (2,4,3,7,9)(2,4,3,8,9)(2,4,2,7,9)(1,4,3,7,9)(1,4,2,8,9)(1,4,2,8,9)
String: 1,5-3,2-1
Combinations: (1,3,1)(1,2,1)(5,3,1)(5,3,1)
for($j = 0; $j < 12; $j++) {
for($k = 0; $k < 8; $k++) {
$ln = $k + 1;
if(...) {
//Code for table edges like row and col names
//end code
} else { //Other cases
//switch statement, looks like
switch($j) {
case 2:
$keyname = $ln.'_FAR_INT';
break;
... //All cases are accounted for in this switch
}
foreach($data as $key => $val) {
if(strpos($keyname, $key) !== false) {
$cellVal = $key;
break;
} else {
$cellVal = '';
}
}
}
}
}
So the problem here is that the variable $ln is stuck at 2 no matter what as soon as it hits a blank row. The first two columns have data from a database, and the third onwards have blanks in their relevant key/value pairs, so they're not returning null, but
If you notice, it gets to 2_FAR_INT, then does that forever until it hits the next row.
I don't know why it does this and debugging it has been a painful endeavor.
Dataset: Looks like {data: 1_FAR_INT, 2_FAR_INT, 3_FAR_INT, etc..., 1_TOTAL_BORN, 2_TOTAL_BORN, 3_TOTAL_BORN,...}
Why does $ln refuse to increment appropriately to $k + 1 in every single case no matter what I tell it to do?
$bar contains 4 (in this example, but potentially much more than 4) values I want to copy into $foo and $blah in this way:
$foo[0] = $bar[0];
$foo[1] = $bar[2];
$blah[0] = $bar[1];
$blah[1] = $bar[3];
So, the even rows of $bar will be copied into $foo[i], and the odd rows will be copied into $blah[i].
I tried with:
for($i=0; $i<2; $i++)
{
for($j=0; $j<4; $j++)
{
if($j % 2 == 0)
{
$foo[$i] = $bar[$j]; // EVEN
}
else
{
$blah[$i] = $bar[$j]; // ODD
}
}
}
However if I show the output of $foo and $blah, $foo[0] is equal to $foo[1], and $blah[0] is equal to $blah[1], while they should contain different values.
Example:
Source:
$bar[0]: 27.8
$bar[1]: Napoli-Posillipo
$bar[2]: 29
$bar[3]: Stadio San Paolo di Napoli, Napoli
(wrong) result of the loop:
$foo[0] = 29 (it should be 27.8)
$foo[1] = 29
$blah[0] = Stadio San Paolo di Napoli, Napoli (it should be Napoli-Posillipo)
$blah[1] = Stadio San Paolo di Napoli, Napoli
Any hints?
Thanks
you have made it to complex, something simple like this should work:
foreach ($bar as $k=>$v){
if($k % 2 == 0){
$foo[] = $v; // EVEN
}else{
$blah[] = $v; // ODD
}
}
what about sth like
foreach($bar as $key => $value) {
if($key % 2 == 0) {
//even
$foo[] = $value;
}
else {
// odd
$blah[] = $value;
}
}
You said it yourself:
"So, the even rows of $bar will be copied into $foo[i], and the odd rows will be copied into $blah[i]".
Cycle all $bar, and copy odd rows into $blah, even into $foo:
for ($i = 0; $i < 4; $i++)
if ($i % 2)
$blah[$i/2] = $bar[$i];
else
$foo[$i/2] = $foo[$i];
In the general case:
switch($i % N) // "N" for Napoli :-D
{
case 0: $VAR1[$i/N] = $bar[$i]; break;
case 1: $VAR2[$i/N] = $bar[$i]; break;
...
}