Converting 1D array to a 2D array with count of elements [duplicate] - php

This question already has answers here:
How to count the consecutive duplicate values in an array?
(6 answers)
Closed last month.
I'm stuck and am wondering if someone could point me in the right direction.
I have an array containing numbers, eg:
$start = array(0,0,0,45,45,0,3,0,0,1,1,1,1);
And would like that array to convert to this array:
$result = array( array('id'=>0, 'aantal'=>3,
array('id'=>45,'aantal'=>2),
array('id'=>0, 'aantal'=>1),
array('id'=>3,'aantal'=>1),
array('id'=>0, 'aantal'=>1),
array('id'=>1,'aantal'=>4)
)
I tried traversing the $start array, but I got stuck onlooking up the n-1 in $start without having the key.
Does anyone have any advice on how I can do this?

This would be the typical approach for run length encoding an array of items:
$array = array(0,0,0,45,45,0,3,0,0,1,1,1,1);
$last = null;
$current = null;
$result = array();
foreach ($array as $item) {
if ($item == $last) {
// increase frequency by 1
++$current['aantal'];
} else {
// the first iteration will not have a buffer yet
if ($current) {
$result[] = $current;
}
// create buffer array item, set frequency to 1
$current = array('id' => $item, 'aantal' => 1);
$last = $item;
}
}
// last pass
if ($current) {
$result[] = $current;
}

Related

PHP : Implode and get the keys of a multidimensional associative array [duplicate]

This question already has answers here:
PHP - Convert multidimensional array to 2D array with dot notation keys
(5 answers)
Closed 2 years ago.
I have a little problem. I want to transform this:
$array['page']['article']['header'] = "Header";
$array['page']['article']['body'] = "Body";
$array['page']['article']['footer'] = "Footer";
$array['page']['news']['header'] = "Header";
$array['page']['news']['body'] = "Body";
$array['page']['news']['footer'] = "Footer";
Into this:
$array['page.article.header'] = "Header";
$array['page.article.body'] = "Body";
$array['page.article.footer'] = "Footer";
$array['page.news.header'] = "Header";
$array['page.news.body'] = "Body";
$array['page.news.footer'] = "Footer";
The number of dimensions is variable and can be times 0 or 10. I don't know if I used the right search term, but Google could not help me so far.
So if someone has a solution for me.
Thanks
You can loop over the array at hand. Now, if the current value is an array, recursively call that array to the function call. On each function call, return an array with key value pairs. When you get the output from your sub-array, attach current key value to all keys of that sub-array returned output.
Snippet:
<?php
function rearrange($array){
$output = [];
foreach($array as $key => $val){
if(is_array($val)){
$out = rearrange($val);
foreach($out as $sub_key => $sub_val){
$output[$key . "." . $sub_key] = $sub_val;
}
}else{
$output[$key] = $val;
}
}
return $output;
}
print_r(rearrange($array));
Demo: https://3v4l.org/40hjK

combine array entries with every other entry

Sorry for the title as it looks like most of the other questions about combining arrays, but I don't know how to write it more specific.
I need a PHP function, which combines the entries of one array (dynamic size from 1 to any) to strings in every possible combination.
Here is an example with 4 entries:
$input = array('e1','e2','e3','e4);
This should be the result:
$result = array(
0 => 'e1',
1 => 'e1-e2',
2 => 'e1-e2-e3',
3 => 'e1-e2-e3-e4',
4 => 'e1-e2-e4',
5 => 'e1-e3',
6 => 'e1-e3-e4',
7 => 'e1-e4'
8 => 'e2',
9 => 'e2-e3',
10 => 'e2-e3-e4',
11 => 'e2-e4',
12 => 'e3',
13 => 'e3-e4',
14 => 'e4'
);
The sorting of the input array is relevant as it affects the output.
And as you see, there should be an result like e1-e2 but no e2-e1.
It seems really complicated, as the input array could have any count of entries.
I don't even know if there is a mathematical construct or a name which describes such a case.
Has anybody done this before?
You are saying that there might be any number of entries in the array so I'm assuming that you aren't manually inserting the data and there would be some source or code entering the data. Can you describe that? It might be easier to directly store it as per your requirement than having an array and then changing it as per your requirement
This might be helpful Finding the subsets of an array in PHP
I have managed to bodge together a code that creates the output you want from the input you have.
I think I have understood the logic of when and why each item looks the way it deos. But Im not sure, so test it carefully before using it live.
I have a hard time explaining the code since it's really a bodge.
But I use array_slice to grab the values needed in the strings, and implode to add the - between the values.
$in = array('e1','e2','e3','e4');
//$new =[];
$count = count($in);
Foreach($in as $key => $val){
$new[] = $val; // add first value
// loop through in to greate the long incrementing string
For($i=$key; $i<=$count-$key;$i++){
if($key != 0){
$new[] = implode("-",array_slice($in,$key,$i));
}else{
if($i - $key>1) $new[] = implode("-",array_slice($in,$key,$i));
}
}
// all but second to last except if iteration has come to far
if($count-2-$key >1) $new[] = Implode("-",Array_slice($in,$key,$count-2)). "-". $in[$count-1];
// $key (skip one) next one. except if iteration has come to far
If($count-2-$key >1) $new[] = $in[$key] . "-" . $in[$key+2];
// $key (skip one) rest of array except if iteration has come to far
if($count-2-$key > 1) $new[] = $in[$key] ."-". Implode("-",Array_slice($in,$key+2));
// $key and last item, except if iteration has come to far
if($count-1 - $key >1) $new[] = $in[$key] ."-". $in[$count-1];
}
$new = array_unique($new); // remove any duplicates that may have been created
https://3v4l.org/uEfh6
here is a modificated version of Finding the subsets of an array in PHP
function powerSet($in,$minLength = 1) {
$count = count($in);
$keys = array_keys($in);
$members = pow(2,$count);
$combinations = array();
for ($i = 0; $i < $members; $i++) {
$b = sprintf("%0".$count."b",$i);
$out = array();
for ($j = 0; $j < $count; $j++) {
if ($b{$j} == '1') {
$out[] = $keys[$j];
}
}
if (count($out) >= $minLength) {
$combinations[] = $out;
}
}
$result = array();
foreach ($combinations as $combination) {
$values = array();
foreach ($combination as $key) {
$values[$key] = $in[$key];
}
$result[] = implode('-', $values);
}
sort($result);
return $result;
}
This seems to work.

Loop throw array, detect max value, and reset prev one

I would like someone to help me with this one, please.
I have this array.
foreach ($callersHistoryArray as $key => $value) {
//check for duplicates and find the highest call duration
if(in_array($value['caller'], $item, true) && $value['process'] == 0)
{
$duplicates = array(
'key' => $key,
'totalTime' => $callersHistoryArray[$key]['totalDurationTime']
);
echo print_r($duplicates, true);
if ($duplicates['totalTime'] > $max) {
$max = $duplicates['totalTime'];
$value['unique'] = 1;
}
}
I loop throw $callersHistoryArray and detect duplicates, create a new array and find the max totalTime from them and set unique value to 1.
When I go to second position in the foreach-loop, the previous one must change unique to 1. But I can't do that. I used prev($callersHistoryArray), to get last one but nothing.
I don't fully understand the question. I suspect you want to start with something like this:
<?php
$duplicates = array();
$maxTime = 0;
$unique = null;
foreach ($callersHistoryArray as $key => $value) {
//check for duplicates and find the highest call duration
if(in_array($value['caller'], $item, true) && $value['process'] == 0)
{
if ($maxTime < $value['totalDurationTime']) {
$maxTime = $value['totalDurationTime'];
$unique = $key;
}
$duplicates[] = $value;
}
}
echo print_r($duplicates, true); // array of duplicates
echo print_r($callersHistoryArray[$unique], true); // item with highest time
Bugs notwithstanding, that should give you an array of the duplicates, and also tell you which item has the maximum duration. I don't know where $item comes from, so YMMV.
You might also need to handle two items having the same max duration.

Undefined offset on comparing elements in foreach loop

Hi I'm trying to compare the dates of 2 elements using a foreach loop. Whenever they match add them to an array and push that array into another one.
The idea for this is that I'll show them all in a table, matching element-dates will have their date column grouped (colspan=n). Using a secondary array I'll be able to use the length of that array as colspan amount.
$elements = array();
$ts_index = 0;
foreach($timesheetweeks as $timesheetweek){
$arr = array();
foreach($timesheetweek->timesheets as $index => $timesheet){
$this_date = $timesheetweek->timesheets[$index]->start_date;
$next_date = $timesheetweek->timesheets[$index + 1]->start_date;
if($this_date == $next_date){
$elements[$ts_index][] = $timesheetweek->timesheets[$index + 1];
} else {
$elements[$ts_index] = $timesheetweek->timesheets[$index];
$ts_index += 1;
}
}
}
Unfortunatly after some headaches and a lost match against Argentinia I get the following error:
Undefined offset: 4
fyi: this is what I try to achieve:
elements [
1 => element1, //diff date
2 => array( //same date array
element2,
element3
),
3 => element4 //diff date
]
Not totally sure about some of the code but this general idea should help:
$elements = array();
$ts_index = -1;
$currentDate = '';
foreach ($timesheetweeks as $timesheetweek) {
foreach ($timesheetweek->timesheets as $index => $timesheet) {
if ($timesheet->start_date != $currentDate) {
// check to see if the last $elements element had just one entry, if so flatten it
if ($ts_index > -1 && count($elements[$ts_index]) == 1) {
$elements[$ts_index] = $elements[$ts_index][0];
}
$currentDate = $timesheet->start_date;
$ts_index++;
// create a new array to store this timesheet and any more that may have the same start_date
$elements[$ts_index] = array();
}
$elements[$ts_index][] = $timesheet;
}
}
// if the last element we added is an array with 1 item, flatten it
if ($ts_index > -1 && count($elements[$ts_index]) == 1) {
$elements[$ts_index] = $elements[$ts_index][0];
}
The item $timesheetweek->timesheets[$index + 1] does not exist when $index reaches its maximium value $index = count($timesheetweek->timesheets) -1;.

all combination between 1-7 without any duplicates

I found this here PHP take all combinations
I modified it further to include n number of sets to the given array. However i am not able to figure out how to not get any duplicate numbers in a set. for example
If the output is
1 , 1, 3, 4
then it should remove the extra '1' and give it as
1,3,4
similarly if there are 2 outputs.
1,3,4,5 and 4,5,3,1
then it should remove one of the duplicate set as well.
I tried using array_unique and thought it could solve half of the issue however it gave a memory allocation error.
<?php
function permutations($arr,$n)
{
$res = array();
foreach ($arr as $w)
{
if ($n==1) $res[] = $w;
else
{
$perms = permutations($arr,$n-1);
foreach ($perms as $p)
{
$res[] = $w." ".$p;
}
}
}
return $res;
}
// Your array
$numbers = array(1,2,3,4,5,6,7);
// Get permutation by groups of n elements
for($i=1; $i<8; $i++)
$pe = permutations($numbers,$i);
$pe = array_unique($pe);
// Print it out
print_r($pe);
?>

Categories