I have a nested array that I want to process into another nested array based on a value in the original.
Here's my original array, it's nested because I'll introduce other values later.
$dataArray = array (
0 => array(
"adgroupid" => "5426058726"
),
1 => array(
"adgroupid" => "5426058086"
),
2 => array(
"adgroupid" => "5426058086"
),
3 => array(
"adgroupid" => "5426058087"
),
4 => array(
"adgroupid" => "5426058087"
),
5 => array(
"adgroupid" => "5426058088"
),
6 => array(
"adgroupid" => "5426058089"
),
7 => array(
"adgroupid" => "5426058089"
),
8 => array(
"adgroupid" => "5426058090"
Here's the result I'm currently getting, note the strings in Array numbers 1 & 2 should be nested in the same array, like in 3 & 5.
array (size=10)
0 =>
array (size=1)
0 => string '5426058726' (length=10)
1 =>
array (size=1)
0 => string '5426058086' (length=10)
2 =>
array (size=1)
0 => string '5426058086' (length=10)
3 =>
array (size=2)
0 => string '5426058087' (length=10)
1 => string '5426058087' (length=10)
4 =>
array (size=1)
0 => string '5426058088' (length=10)
5 =>
array (size=2)
0 => string '5426058089' (length=10)
1 => string '5426058089' (length=10)
6 =>
array (size=4)
0 => string '5426058090' (length=10)
Here's my code, I need to use the if statement because at a later stage I want to introduce another argument:
$newdataArray = array();
$j = 0; // Set value of working variables
$adgroupidcheck = 0;
foreach ($dataArray as $value) { // Loop through the array
if( $adgroupidcheck != $value['adgroupid'] ) { // Check $adgroupidcheck
$newdataArray[][] = $value['adgroupid']; // Create a new nested array
$j ++; // increment $j
} else {
$newdataArray[$j][] = $value['adgroupid']; // Add to the current array
}
$adgroupidcheck = $value['adgroupid']; // Set $adgroupidcheck
}
So my problem is that my code only works after the first instance of the array check loop hasn't worked.
Any help would be appreciated.
Thank you.
You should just pre-increment your $j value so it get added as the correct array. Otherwise it's sent to the next one, just make a quick trace.
if( $adgroupidcheck != $value['adgroupid'] ) {
$newdataArray[++$j][] = $value['adgroupid'];
} else {
$newdataArray[$j][] = $value['adgroupid'];
}
foreach ($dataArray as $value) {
if( $adgroupidcheck != $value['adgroupid'] ) {
$newdataArray[][] = $value['adgroupid'];
$j ++; // increment $j
} else {
$j--; //decrease j which was incremented after inserting one value
$newdataArray[$j][] = $value['adgroupid'];
$j++; // increment it again for it's original or new index
}
$adgroupidcheck = $value['adgroupid'];
}
Related
What I am trying to get is to remove duplicate values in the Rest field, but I want to assign / keep its date in the original. element:
array (size=413)
0 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520980
'Rest' => 123abc
1 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520981
'Rest' => qwe123
2 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520983
'Rest' => qwe123
I try it but it doesn't work
public function find_repeats($arr)
{
foreach(array_column($arr, 'Rest') as $ckey=>$value) {
$keys = array_reverse(array_keys(array_column($arr, 'Rest'), $value));
foreach ($keys as $v) {
if ($ckey != $v && isset($arr[$v]))
{
$arr[$ckey]['Date'][] = $arr[$v]['Date'][0];
unset($arr[$v]);
}
}
}
return $arr;
}
This is what the table should look like after this operation
array (size=413)
0 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520980
'Rest' => 123abc
1 =>
array (size=5)
'Date' =>
array (size=1)
0 => int 1588520981
1 => int 1588520983
'Rest' => qwe123
Thanks for help! :)
Simple solution without all these stacked functions:
$newData = [];
foreach ($arr as $item) {
$rest = $item['Rest'];
if (!isset($newData[$rest])) {
$newData[$rest] = $item;
} else {
$newData[$rest]['Date'][] = $item['Date'][0];
}
}
// optionally apply array_values to get 0-indexed array:
$newData = array_values($newData);
How to construct data into a binary tree sort to output a one-dimensional array?
Now that I have constructed the data into a binary tree, how can I recursively solve the binary tree as a one-dimensional array with the following code and data:
Data
$nodes = array(8,3,10,1,6,14,4,7,13);
Construct a binary tree code
function insertNode($node,$newNode){
//var_dump($node);
//var_dump($newNode);
//exit;
if ($node['key'] < $newNode['key']){
if (empty($node['right'])){
$node['right'] = $newNode;
}else{
$node['right'] = insertNode($node['right'],$newNode);
}
}elseif ($node['key'] > $newNode['key']){
if (empty($node['left'])){
$node['left'] = $newNode;
}else{
$node['left'] = insertNode($node['left'],$newNode);
}
}
return $node;
}
function tree($nodes)
{
$node = [
'key' => '',
'left' => '',
'right' => ''
];
$newNode = [
'key' => '',
'left' => '',
'right'=> ''
];
foreach ($nodes as $key => $value){
//insert($value,$key);
if($key == 0)
{
$node['key'] = $value;
continue;
}
$newNode['key'] = $value;
//Constructing a binary tree
$node = insertNode($node,$newNode);
}
//Recursive solution
$node = midSortNode($node);
return $node;
}
var_dump(tree($nodes));
The following is my constructed binary tree
array (size=3)
'key' => int 8
'left' =>
array (size=3)
'key' => int 3
'left' =>
array (size=3)
'key' => int 1
'left' => string '' (length=0)
'right' => string '' (length=0)
'right' =>
array (size=3)
'key' => int 6
'left' =>
array (size=3)
...
'right' =>
array (size=3)
...
'right' =>
array (size=3)
'key' => int 10
'left' => string '' (length=0)
'right' =>
array (size=3)
'key' => int 14
'left' =>
array (size=3)
...
'right' => string '' (length=0)
I need to recursively classify the binary tree into a well-ordered one-dimensional array.
My code is as follows
function midSortNode($node){
$sortArr = [];
if (!empty($node)){
$sortArr[] = midSortNode($node['left']);
//$sortArr['left'] = midSortNode($node['left']);
array_push($sortArr,$node['key']);
$sortArr[] = midSortNode($node['right']);
//$sortArr['right'] = midSortNode($node['right']);
}
return $sortArr;
}
var_dump(midSortNode($node));
Here is the result, but not what I want
0 =>
array (size=3)
0 =>
array (size=3)
0 =>
array (size=0)
...
1 => int 1
2 =>
array (size=0)
...
1 => int 3
2 =>
array (size=3)
0 =>
array (size=3)
...
1 => int 6
2 =>
array (size=3)
...
1 => int 8
2 =>
array (size=3)
0 =>
array (size=0)
empty
1 => int 10
2 =>
array (size=3)
0 =>
array (size=3)
...
1 => int 14
2 =>
array (size=0)
...
How to solve the binary tree as follows
array (size=9)
0 => int 1
1 => int 3
2 => int 4
3 => int 6
4 => int 7
5 => int 8
6 => int 10
7 => int 13
8 => int 14
I'm assuming that your happy with the steps so far, so the main code as it is isn't changed. All I think you need to do is to extract the data from the final tree into a 1 dimensional array. As the items are all leaf nodes and in order, you can just use array_walk_recursive() to go over all of the nodes and add them to a new array...
$tree = tree($nodes);
array_walk_recursive( $tree,
function ($data) use (&$output) { $output[] = $data;} );
print_r($output);
gives...
Array
(
[0] => 1
[1] => 3
[2] => 4
[3] => 6
[4] => 7
[5] => 8
[6] => 10
[7] => 13
[8] => 14
)
Edit:
To update the existing code to do this, you can change the midSortNode() to pass around the list of outputs and only add in the current node...
function midSortNode($node, $sortArr = []){
if (!empty($node)){
$sortArr = midSortNode($node['left'], $sortArr);
$sortArr[] = $node['key'];
$sortArr = midSortNode($node['right'], $sortArr);
}
return $sortArr;
}
From this foreach:
foreach ($statisticheProdotti as $values) {
$prod[] = $values['nome'];
$nomi = array_values(array_unique($prod, SORT_REGULAR));
$arr = array_combine(range(1, 12), range(1, 12));
foreach ($arr as $key => $val) {
$data = ($val == $values['mese']) ? $values['data'] : 0;
$arr[$val] = $data;
}
$prodotti[] = ['name' => $values['nome'], 'data' => array_values($arr)];
}
I get this array:
array (size=14)
0 =>
array (size=2)
'name' => string 'COMBIART PLUS' (length=13)
'data' =>
array (size=12)
0 => string '92' (length=2)
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
11 => int 0
1 =>
array (size=2)
'name' => string 'COMBIART PLUS' (length=13)
'data' =>
array (size=12)
0 => int 0
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
11 => string '92' (length=2)
2 =>
array (size=2)
'name' => string 'SECUR' (length=10)
'data' =>
array (size=12)
0 => string '5' (length=1)
1 => int 0
2 => int 0
3 => int 0
4 => int 0
5 => int 0
6 => int 0
7 => int 0
8 => int 0
9 => int 0
10 => int 0
11 => int 0
3 =>
.....`
I need to remove duplicated name and have unique array data.
Final output should be (example from index 0 and 1 which have same 'name'):
['name' => 'COMBIART PLUS', 'data' => [92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92]].
I hope I've well explained my problem.
Thanks
Sorry it's taken me a while to respond to this.
This might not be the most elegant way to do this, but assuming you want to combine the arrays with the same name, and combine the data array to make a unique array by using the values and the keys (assuming zero is not useful here), you can do something like this:
$output = array();
foreach ($example as $data) {
// Use the name as a quick array key reference to avoid having to search a second level of the array
$key = $data['name'];
if (!array_key_exists($key, $output)) {
// Instantiate the first entry using the name as the array key (we can reset this later)
$output[$key] = array(
'name' => $key,
'data' => $data['data']
);
// Skip the rest of this loop
continue;
}
// An entry already exists for the name, so merge any unique values into the array using the
// keys AND values to determine if something is unique. Zero is treated as empty.
foreach ($data['data'] as $newKey => $newValue) {
if (empty($output[$key]['data'][$newKey])) {
// Add a new unique entry to the output array (zero counts as empty here)
$output[$key]['data'][$newKey] = $newValue;
}
}
}
// Remove the name from the keys now
$output = array_values($output);
This should give you the result you're after. Example here.
thanks for your help scrowler, thanks to your code I have been able to get what I needed but I've just changed something to adapt it to my project...
function generateChartData($array) {
$prodArr = [];
$oldProd = '';
$arr = array_fill(0, 12, 0);
foreach ($array as $values) {
$Prod = $values['name'];
if ($Prod !== $oldProd) {
if (!empty($oldProd)) {
$prodotti[] = ['name' => $oldProd, 'data' => $arr];
}
$oldProd = $Prod;
}
foreach ($arr as $key => $val) {
if ($key == $values['mese'] - 1) {
$arr[$key] = (int) $values['data'];
}
}
}
// get last item
if (!empty($oldProd)) {
$prodArr[] = ['name' => $oldProd, 'data' => $arr];
}
return $prodArr;
}
This Question might seem duplicate, but I swear to have tried and tried thousands of solutions for many hours now...
I have got an associative multidimentional array like this:
1 =>
array (size=1)
'Pld' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
2 =>
array (size=1)
'Aln' =>
array (size=2)
'score_good_answers' => string '0' (length=1)
'score_bad_answers' => string '1' (length=1)
3=>
array (size=1)
'IPS' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
4 =>
array (size=1)
'Pld' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
5 =>
array (size=1)
'Aln' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
6 =>
array (size=1)
'Aln' =>
array (size=2)
'score_good_answers' => string '1' (length=1)
'score_bad_answers' => string '0' (length=1)
FOR Var_Export:
1=> array ( 'Pld' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 2 => array ( 'Aln' => array ( 'score_good_answers' => '0', 'score_bad_answers' => '1', ), ), 3 => array ( 'IPS' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 4 => array ( 'Pld' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 5 => array ( 'Aln' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ), 6 => array ( 'Aln' => array ( 'score_good_answers' => '1', 'score_bad_answers' => '0', ), ),
I need to SUM the all the 'score_good_answers' and the 'score_bad_answers' for all Alns and Plds and so forth.
The Worse case scenario is that, this keys i.e: are changeable values.
At this level, whatever solution that works will be well appreciated.
I tried the Accepted Answer in this SO Question: How to sum values of the array of the same key?
However, It seems to throw several Errors....
And I Tried Several More Solutions from several SO Questions,
i.e: How to sum values of the array of the same key?, Array sum of value based on same key, How to sum values via the same key and group by other key and many more...
An other close one was this:How to sum same array in php
And tried:
$array2 = array();
for($f = 0; $f<count($getCategories); $f++){
foreach($getCategories[$i] as $k=>$v) {
if(!isset($array2[$v['Aln']])) {
$array2[$v['Aln']] = $v;
} else {
$array2[$v['Aln']]['score_good_answers'] += $v['score_good_answers'];
}
}
} var_dump($array2);
I still get Several Errors including invalid arguments undefined offsets and many more
Humbly request for any suggestion.
Thank you very much
You can use this code:
$answers = array();
foreach ($getCategories as $categories){
foreach($categories as $category => $scores){
foreach ($scores as $type => $score){
if (isset($answers[$category][$type])){
$answers[$category][$type] += (int) $score;
} else {
$answers[$category][$type] = (int) $score;
}
}
}
}
The output of will be the following array:
Array
(
[Pld] => Array
(
[score_good_answers] => 2
[score_bad_answers] => 0
)
[Aln] => Array
(
[score_good_answers] => 2
[score_bad_answers] => 1
)
[IPS] => Array
(
[score_good_answers] => 1
[score_bad_answers] => 0
)
)
The variable that holds the key is named $f, but you try to use the undefined variable $i on the next line, see? That is one of your warnings and will not do what you want it to. Use $f on the second line.
for($f = 0; $f<count($getCategories); $f++){
foreach($getCategories[$i] as $k=>$v) {
Your data structure seems a bit odd? Is there always just one key in the second top-most array?
This would be prettier if possible:
array(2) {
[0] => stdClass#1 (3) {
public $name => string(4) "Pld"
public $score_good_answers => int(1)
public $score_bad_answers=> int(0)
}
[1] => stdClass#1 (3) {
public $name => string(4) "Aln"
public $score_good_answers => int(0)
public $score_bad_answers=> int(1)
}
}
I can not see what end result you want, but give this a try, might not fit what you want though.
$goodAnswersByCategoryDataKey = array();
$badAnswersByCategoryDataKey = array();
foreach ($categories as $i => $category) {
foreach ($category as $categoryDataKey => $categoryData) {
if (!isset($goodAnswersByCategoryDataKey[$categoryDataKey])) {
$goodAnswersByCategoryDataKey[$categoryDataKey] = 0;
}
$goodAnswersByCategoryDataKey[categoryDataKey] += $categoryData['score_good_answers'];
if (!isset($badAnswersByCategoryDataKey[$categoryDataKey])) {
$badAnswersByCategoryDataKey[$categoryDataKey] = 0;
}
$badAnswersByCategoryDataKey[$categoryDataKey] += $categoryData['score_bad_answers'];
}
}
var_dump(goodAnswersByCategoryDataKey);
var_dump(badAnswersByCategoryDataKey);
If it's an iterative structure like in your example you can do this :
$answers = [];
$nbCat = count($getCategories);
for($i = 0; $i < $nbCat; $i++) {
foreach($getCategories[$i] as $key => $scores) {
if(empty($answers[$key])) {
$answers[$key] = $scores;
}
else {
$answers[$key]['score_good_answers'] += $scores['score_good_answers'];
$answers[$key]['score_bad_answers'] += $scores['score_bad_answers'];
}
}
}
I've got an array that looks like this:
'coilovers' =>
'strut_and_individual_components' =>
'complete_strut' =>
0 =>
array (size=5)
'achse' => string 'Oś tylnia' (length=10)
'position' => string 'Prawo' (length=5)
'material' => string 'Stal' (length=4)
'variante' => string 'Wariant 3' (length=9)
'img' => string 'gewindefahrwerk_federbein_komplett_level3.png'
'hls_components' =>
'assembly_pump_unit' =>
0 =>
'achse' => string 'Assembly pump unit' (length=18)
'img' => string 'hls_komponenten_baugruppe_pumpeneinheit_level3.png'
Now I'm getting string parameter that looki for example like : [coilovers][strut_and_individual_components][complete_strut][0]
And now I want to to unset whole branch of that array based on that parameter. So far I've accomplished how to read value but that parameter and it looks like.
private function str_index_array(&$arr, $indexes) {
$arr_indexes = explode('][',trim($indexes,'[]'));
$session_array = &$arr;
foreach($arr_indexes as $index) {
$session_array = &$session_array[$index];
}
}
But I'm stuck now, I need to check if that element is last element in array and in previous element is that previous element is empty if its empty unset whole brunch. Any ideas?
I'm sure some PHP/array/reference expert can come up with better ways of doing this, but here is one bug-ugly solution. I've set up a loop to obtain a reference to the last but second level index, and test and delete the sub-indexes from there. Note that there is no error-checking to test if the indexes actually exist before using them.
<?php
$a = array (
'coilovers' => array (
'strut_and_individual_components' => array (
'complete_strut' => array (
0 => array (
'achse' => 'Os tylnia',
'position' => 'Prawo',
'material' => 'Stal',
'variante' => 'Wariant 3',
'img' => 'gewindefahrwerk_federbein_komplett_level3.png'
)
)
)
),
'hls_components' => array (
'assembly_pump_unit' => array (
0 => array (
'achse' => 'Assembly pump unit',
'img' => 'hls_komponenten_baugruppe_pumpeneinheit_level3.png'
)
)
)
);
function delete_index (&$arr, $indexes) {
$arr_indexes = explode('][',trim($indexes,'[]'));
for ($i = 0; $i < count($arr_indexes) - 2; $i++) {
$arr = &$arr[$arr_indexes[$i]];
}
$ix1 = $arr_indexes[$i];
$ix2 = $arr_indexes[$i+1];
unset ($arr[$ix1][$ix2]);
if (empty ($arr[$ix1]))
unset ($arr[$ix1]);
}
print_r ($a);
delete_index ($a, '[coilovers][strut_and_individual_components][complete_strut][0]');
print_r ($a);