Group array into sub arrays of 2 elements, last group missing - php

I fetch data from my database and it returns 6 rows. I loop over them add them to a temporary array and then every 2 iterations I add them to a parent array so I will know have an array with sub arrays grouped by 2. Below, as you can see, I echo out each iteration for 6 results. My grouped array is only showing 2 groups of 2 when it should be 3 groups of 2. What am I doing wrong?
Note: I checked the data and the first 2 groups are correct data, but the last 2 rows are missing.
// group entries into subgroups of 2
$buffer = array();
$entries = array();
for( $i = 0; $i < $journal_entries_count; $i++ )
{
if( $i % 2 == 0 && $i > 0 )
{
$entries[] = $buffer;
unset( $buffer );
$buffer = array();
}
$buffer[] = $journal_entries[ $i ];
echo $i, '<br />';
}
0
1
2
3
4
5
Array
(
[0] => Array
(
[0] => Array
(
[journal_entry_id] => 196
[journal_entry_date] => 2014-10-24 20:01:44
[scoring_type_id] => 1
[score] => 2662.00
[wod_title] => yyyyy
[wod_date] => 2014-09-12
[strength] =>
[repscheme] =>
[benchmark] => Annie
)
[1] => Array
(
[journal_entry_id] => 197
[journal_entry_date] => 2014-10-24 20:01:44
[scoring_type_id] => 1
[score] => 196.00
[wod_title] => yyyyy
[wod_date] => 2014-09-12
[strength] =>
[repscheme] =>
[benchmark] => Badger
)
)
[1] => Array
(
[0] => Array
(
[journal_entry_id] => 195
[journal_entry_date] => 2014-10-24 20:00:19
[scoring_type_id] => 1
[score] => 300.00
[wod_title] => Koala Bear WOD
[wod_date] => 2014-10-21
[strength] =>
[repscheme] =>
[benchmark] => Amanda
)
[1] => Array
(
[journal_entry_id] => 194
[journal_entry_date] => 2014-10-24 20:00:19
[scoring_type_id] => 7
[score] => 5.20
[wod_title] => Koala Bear WOD
[wod_date] => 2014-10-21
[strength] => Back Squat
[repscheme] => 10RM
[benchmark] =>
)
)
)
Solution?
I'm not marking it as a solution yet because I'm not sure it will work in all cases,
but loop at each iteration it never hits the last one.
0 = skip - add
1 = skip - add
2 = add - add
3 = skip - add
4 = add - add
5 = skip - add
I added $journal_entries_count + 1 and the results are now correct.
Thoughts?

If $journal_entries_count is 6, then at the end of your loop, $buffer will contain two rows, but it won't have been added to $entries.
You need to add a final
$entries[] = $buffer;
after the loop. Alternatively, you could use array_chunk:
$entries = array_chunk($journal_entries, 2);

can you try it with some simpler code like this and see how you go.
$entries = array();
$journal_entries[] = 1;
$journal_entries[] = 2;
$journal_entries[] = 3;
$journal_entries[] = 4;
$journal_entries[] = 5;
while (count($journal_entries)){
$entries[] = array_slice($journal_entries,0,2);
$journal_entries = array_slice($journal_entries,2);
}
print_r($entries);

You are missing the last 2 entries because you don't add the buffer from the last loop.
You need to update your code and after the foreach loop, check if the buffer is empty or not. If it's not empty then add it to the final array.
You say that for $journal_entries_count + 1 it works, because you actually run the loop one more time and adds the final buffer from the "true" last loop.
The end code should be something like this:
$buffer = array();
$entries = array();
for( $i = 0; $i < $journal_entries_count; $i++ ) {
if( $i % 2 == 0 && $i > 0 ) {
$entries[] = $buffer;
unset( $buffer );
$buffer = array();
}
$buffer[] = $journal_entries[ $i ];
echo $i, '<br />';
}
// add any leftover buffer data
if(count($buffer) > 0) {
$entries[] = $buffer;
}

Related

Get random elements from array and show how many times occurs in the array

I have long string which I split after each 4th char. After that I want to take 3 random of them and show how many times are in the array.
What I have is
$string = "AAAAAAABAAACAAADAAAEAAAFAAAGAAAHAAAIAAAJAAAKAAALAAAMAAANAAAOAAAPAAAQAAARAAASAAATAAAUAAAVAAAWAAAXAAAYAAAZAAAaAAAbAAAcAAAdAAAeAAAfAAAgAAAhAAAiAAAjAAAkAAAlAAAmAAAnAAAoAAApAAAqAAArAAAsAAAtAAAuAAAvAAAwAAAxAAAyAAAzAABAAABBAABCAABDAABEAABFAABGAABHAABIAABJAABKAABLAABMAABNAA";
$segmentLength = 3;
$totalLength = strlen($string);
for ($i = 0; $i < $totalLength; $i += $segmentLength) {
$result[] = substr($string, min($totalLength - $segmentLength, $i), $segmentLength);
}
print_r(array_rand(array_count_values($result), 4));
array_count_values($result) output is
Array
(
[AAA] => 19
[ABA] => 1
[AAC] => 1
........
[AAL] => 1
[MAA] => 1
[AAB] => 4
)
I'm trying with print_r(array_rand(array_count_values($result), 4)); to output
Array
(
[AAA] => 19
[ABA] => 1
[AAC] => 1
[AAB] => 4
)
or
Array
(
[ABA] => 1
[AAC] => 1
[AAL] => 1
[MAA] => 1
)
instead I get
Array
(
[0] => AHA
[1] => AAa
[2] => zAA
[3] => BGA
)
...
Array
(
[0] => GAA
[1] => AxA
[2] => CAA
[3] => BGA
)
... so on
You could store the result of array_count_values($result); to a variable and then get a random set of keys from that result. Then loop through that random list of keys and generate your desired output. For example:
$string = "AAAAAAABAAACAAADAAAEAAAFAAAGAAAHAAAIAAAJAAAKAAALAAAMAAANAAAOAAAPAAAQAAARAAASAAATAAAUAAAVAAAWAAAXAAAYAAAZAAAaAAAbAAAcAAAdAAAeAAAfAAAgAAAhAAAiAAAjAAAkAAAlAAAmAAAnAAAoAAApAAAqAAArAAAsAAAtAAAuAAAvAAAwAAAxAAAyAAAzAABAAABBAABCAABDAABEAABFAABGAABHAABIAABJAABKAABLAABMAABNAA";
$segmentLength = 3;
$totalLength = strlen($string);
for ($i = 0; $i < $totalLength; $i += $segmentLength) {
$result[] = substr($string, min($totalLength - $segmentLength, $i), $segmentLength);
}
$countedValues = array_count_values($result);
$randValues = array_rand($countedValues, 4);
$output = [];
for ($i = 0; $i < count($randValues); $i++) {
$key = $randValues[$i];
$output[$key] = $countedValues[$key];
}
print_r($output);

How to decrease value by designed order. For loop seems to break in the middle

I would like to make a function that decreases values of an array by specific order.
the values should be decreased by order noodle -> bread -> rice.
I tried to make the function below.
But it does not work well.
the loop break before achiving array_sum($stapleArray) ===$sizeDayArray.
$stapleArray
should be deducted until the total size equals $sizeDayArray
E.g.
input
targetWeekDayArrayArray
(
[0] => tue
[1] => wed
[2] => fri
[3] => sat
)
*size = 4
$sizeDayArray = size_of($targetWeekDayArrayArray)
$stapleArray=
Array
(
[rice] => 5
[bread] => 0
[noodle] => 1
)
expected result
$stapleArray=
Array
(
[rice] => 4
[bread] => 0
[noodle] => 0
)
caller
$differenceSettingAndDay = array_sum($stapleArray)- sizeof($targetWeekDayArray);
$size = sizeof($targetWeekDayArray);
$stapleArray= $this->substractStapleFood($differenceSettingAndDay,$stapleArray, $size);
private function substractStapleFood($substractionnumber,$stapleArray,$sizeDayArray)
{
$array_key = ['noodle','bread','rice'];
for($i = 0; array_sum($stapleArray) ===$sizeDayArray ; $i++ )
{
$i_mod = $i % count($stapleArray); //$i % 3
$key = $array_key[$i_mod];
if (isset($stapleArray[$key]) && $stapleArray[$key] > 0) {
$stapleArray[$key]--;
}
}
return $stapleArray;
}
Actual result
Array
(
[rice] => 5
[bread] => 0
[noodle] => 1
)
It seems that id did not go through the loop.
Wrong in line :
for($i = 0; array_sum($stapleArray) ===$sizeDayArray ; $i++ )
condition array_sum($stapleArray) ===$sizeDayArray start is false => loop is not running
Change same as :
for($i = 0; !(array_sum($stapleArray) ===$sizeDayArray) ; $i++ )

PHP For loop skips the first outcome

I'm trying to fill an array with a for loop. This is done to get the amount of pages a certain book has. but when executing the code, it skips the first object in the array. Can anyone tell me why? (I thought it was because $i starts at 1 instead of 0 but that doesn't seem to change anything)
if(!empty($article['finishing'])){
$numPages = $article['copies'];
$arrayIndexNumber = [];
for($i=1; $i <= $numPages; $i++){
$arrayIndexNumber[] = $i;
}
if(count($arrayIndexNumber) >= 1 ){
if(count($arrayIndexNumber) == 1){
$output['attributes']['EFPageRange'] = 1;
$print_jobs[$article['id']][] = $output;
}
if(count($arrayIndexNumber) > 1){
$comma_separated1 = implode(", ", ['1', $article['copies']]);
$output['attributes']['EFPageRange'] = $comma_separated1;
$print_jobs[$article['id']][] = $output;
}
array_shift($arrayIndexNumber);
array_pop($arrayIndexNumber);
$comma_separated2 = implode(", ", $arrayIndexNumber);
$output['attributes']['EFPageRange'] = $comma_separated2;
if(count($arrayIndexNumber) >= 2){
$print_jobs[$article['id']][] = $output;
}
}
$article['file_url'] = 'i has finishing';
$output['attributes']['username'] = $article['file_url'];
}
above code outputs:
[0] => Array
(
[attributes] => Array
(
[title] => 277569
[EFPrintSize] => a4
[num copies] => 1
[num pages] => 119
[EFPCName] => 80
[EFDuplex] => TopTop
[EFPageRange] => 1, 119
)
)
instead of:
[0] => Array
(
[attributes] => Array
(
[title] => 277564
[EFPrintSize] => a4
[num copies] => 1
[num pages] => 45
[EFPCName] => 80
[EFDuplex] => false
[EFPageRange] => 1, 45
[username] => i has finishing
[EFColorMode] => Grayscale
)
)
Your first array element is deleted because of array_shift:
array_shift($arrayIndexNumber);
array_shift
array_shift — Shift an element off
the beginning of array
Debug your code:
for($i=1; $i <= $numPages; $i++){
$arrayIndexNumber[] = $i;
}
echo '<pre>';
print_r($arrayIndexNumber); // Check what the array returns
php array indexes starts to count from zero
for($i=1; $i <= $numPages; $i++)
^^^
change it to $i=0

how to use round robin method in array in php?

Hi i am trying to create a sub array from an array.i.e; think I have an array such as given below
$array = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}
which I explode and assign it to a variable $i..
and run the for loop as shown below..
for ( $i=0;$i<count($array);$i++) {
$a = array();
$b = $array[$i];
for($j=0;$j<count($array);$j++){
if($b != $array[$j]){
$a[] = $array[$j];
}
}
the output I want is when
$i = 1
the array should be
{2,3,4,5,6,7,8,9,10,11}
and when
$i = 2
the array should be
{3,4,5,6,7,8,9,10,11,12}
similarly when
$i=19
the array should be
{1,2,3,4,5,6,7,8,9,10}
so how can I do it.
Assuming $i is supposed to be an offset and not the actual value in the array, you can do
$fullArray = range(1, 19);
$i = 19;
$valuesToReturn = 10;
$subset = iterator_to_array(
new LimitIterator(
new InfiniteIterator(
new ArrayIterator($fullArray)
),
$i,
$valuesToReturn
)
);
print_r($subset);
This will give your desired output, e.g.
$i = 1 will give 2 to 11
$i = 2 will give 3 to 12
…
$i = 10 will give 11 to 1
$i = 11 will give 12 to 2
…
$i = 19 will give 1 to 10
$i = 20 will give the same as $i = 1 again
and so on.
$array = range(1, 19);
$i = 19;
$result = array();
$after = array_slice($array, $i, 10);
$before = array_slice($array, 0, 10 - count($after));
$result = array_merge($after, $before);
var_dump(json_encode($result));
P.S. please note 0 element has 1 value and so on...
for ($i = 0; $i < count($array); $i++) {
if ($i + 10 < count($array))
$a = array_slice($array, $i, 10);
else
$a = array_merge(array_slice($array, $i), array_slice($array, 0, 10-(count($array)-$i)));
// do something with $a before it is over-written on the next iteration
}
This test:
<?php
$array = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
for ($i = 0; $i < count($array); $i++) {
if ($i + 10 < count($array))
$a = array_slice($array, $i, 10);
else
$a = array_merge(array_slice($array, $i), array_slice($array, 0, 10-(count($array)-$i)));
echo "<h2>$i</h2>\n<pre>".print_r($a,true)."</pre><br />\n";
}
Resulted in this:
0
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 10
)
...
9
Array
(
[0] => 10
[1] => 11
[2] => 12
[3] => 13
[4] => 14
[5] => 15
[6] => 16
[7] => 17
[8] => 18
[9] => 19
)
10
Array
(
[0] => 11
[1] => 12
[2] => 13
[3] => 14
[4] => 15
[5] => 16
[6] => 17
[7] => 18
[8] => 19
[9] => 1
)
...
18
Array
(
[0] => 19
[1] => 1
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
)
This works fine from my end
<?php
$array = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19);
$size = sizeof($array); // Defining the array size
$str = 17; // This is the reference value from which you have to extract the values
$key = array_search($str, $array);
$key = $key+1; // in order to skip the given reference value
$start = $key%$size;
$end = $start+9;
for($i=$start; $i<=$end; $i++) {
$j = ($i%$size);
$result[] = $array[$j];
}
echo '<pre>'; print_r($result);
?>
It looks like all you need is a slice of a certain size from the array, slice that wraps around the array's end and continues from the beginning. It treats the array like a circular list.
You can achieve this in many ways, one of the simplest (in terms of lines of code) is to extend the original array by appending a copy of it at its end and use the PHP function array_slice() to extract the slice you need:
function getWrappedSlice(array $array, $start, $count = 10)
{
return array_slice(array_merge($array, $array), $start, $count);
}
Of course, you have to be sure that $start is between 0 and count($array) - 1 (including), otherwise the value returned by the function won't be what you expect.
Round-robin on an array can be achieved by doing a "rotate" operation inside each iteration:
for ($i = 0; $i < count($array); ++$i) {
// rotate the array (left)
array_push($array, array_shift($array));
// use $array
}
During the loop, the first element of the array is placed at the back. At the end of the loop, the array is restored to its original value.

Breaking an array into groups based on values

Using PHP, I'm trying to break an array up into multiple arrays based on groups of values. The groups are based on the values being between 1 and 5. But here's the hard part...
I need to loop through the array and put the first set of values that are between 1 and 5 in their own array, then the next set of values that are between 1 and 5 in their own array, and so on.
But each group WON'T always include 1,2,3,4,5. Some groups could be random.
Examples:
1,1,2,2,3,4,5 - this would be a group
1,2,3,4,4,4 - this would be a group
1,2,3,3,5 - this would be a group
2,2,3,3,5 - this would be a group
So I can't just test for specific numbers.
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 1
[6] => 2
[7] => 3
[8] => 4
[9] => 4
[10] => 1
[11] => 1
[12] => 3
[13] => 4
[14] => 5
)
Any Ideas?
I would just check if the current value is larger than the previous value, and if yes, begin a new group.
$groups = array();
$groupcount = 1;
foreach( $array as $key=>$value )
{
if( $key > 0 ) // there's no "previous value" for the first entry
{
if( $array[$key] < $array[$key-1] )
{
$groupcount = $groupcount + 1;
}
}
$group[groupcount][] = $value;
}
Is this what you are looking for?
$groups = array();
$cur = array();
$prev = 0;
foreach ($numbers as $number)
{
if ($number < $prev)
{
$groups[] = $cur;
$cur = array();
}
$cur[] = $number;
$prev = $number;
}
if ($cur) $groups[] = $cur;
Untested. (Edit: corrected some obvious mistakes.)

Categories