How to get list all multidimensional array with parent index - php

How to get list all multidimensional array with parent index. All index in each level is unique and i want to show all list with the level.
example my arrays:
Array(
[1] => Array(
[2] => Array(
[3] =>
[4] =>
[7] =>
)
)
[6] => Array(
[11] => Array(
[12] => Array(
[17] =>
)
)
)
[2] => Array(
[13] => Array(
[14] =>
)
)
)
I want to get output like this:
Array
(
[1]=array([level] = 1)
[2]=array([level] = 2)
[3]=array([level] = 3)
[4]=array([level] = 3)
[7]=array([level] = 3)
[6]=array([level] = 1)
[11]=array([level] = 2)
[12]=array([level] = 3)
[17]=array([level] = 4)
...
)

Here is a solution using a recursive function. Assuming your array will have a NULL value if there is no more child/nested arrays.
$arr = array(1 => array(2 => array(3 => NULL,
4 => NULL,
7 => NULL )),
6 => array(11 => array(12 => array(17 =>NULL))),
2 => array(13 => array(14 => NULL)));
$rslt_arr = array();
function traverse_arr($array, $level)
{
$level++;
foreach ($array as $key => $value){
if($value != NULL){
traverse_arr($value, $level);
}
$GLOBALS['rslt_arr'][$key]['level'] = $level;
}
}
traverse_arr($arr, 0);
echo '<pre>';
print_r($rslt_arr);
OUTPUT:
Array
(
[3] => Array
(
[level] => 3
)
[4] => Array
(
[level] => 3
)
[7] => Array
(
[level] => 3
)
[2] => Array
(
[level] => 1
)
[1] => Array
(
[level] => 1
)
[17] => Array
(
[level] => 4
)
[12] => Array
(
[level] => 3
)
[11] => Array
(
[level] => 2
)
[6] => Array
(
[level] => 1
)
[14] => Array
(
[level] => 3
)
[13] => Array
(
[level] => 2
)
)

Related

how to check if the element of an array is changed

Sorry I don't know the actual title of my question. I have a problem with a php array.
my array is like :
$Array =
(
[0] => Array
(
[Product] => Array
(
[cat_id] => 7
[subcat_id] => 1
)
)
[1] => Array
(
[Product] => Array
(
[cat_id] => 7
[subcat_id] => 1
)
)
[2] => Array
(
[Product] => Array
(
[cat_id] => 8
[subcat_id] => 2
)
)
[3] => Array
(
[Product] => Array
(
[cat_id] => 9
[subcat_id] => 3
)
)
[4] => Array
(
[Product] => Array
(
[cat_id] => 9
[subcat_id] => 3
)
)
)
Now I want to insert
[Subcat]=>'changed'
if the subcat_id is changed . How to check if the subcat_id is changed on the next key value.please help.
I have tried this :
$sub_cat_last = '';
foreach ($Array as $key => $p) {
$sub_cat = $p['Product']['subcat_id'];
if($sub_cat != $sub_cat_last){
$Array[$key]['Subcat'] = 'change';
$sub_cat_last = $p['Product']['subcat_id'];
}
}
But not working properly.
I want my array like :
Array
(
[0] => Array
(
[Product] => Array
(
[cat_id] => 7
[subcat_id] => 1
)
)
[1] => Array
(
[Product] => Array
(
[cat_id] => 7
[subcat_id] => 1
)
)
[2] => Array
(
[Product] => Array
(
[Subcat] => change
)
)
[3] => Array
(
[Product] => Array
(
[cat_id] => 8
[subcat_id] => 2
)
)
[4] => Array
(
[Product] => Array
(
[Subcat] => change
)
)
[5] => Array
(
[Product] => Array
(
[cat_id] => 9
[subcat_id] => 3
)
)
[6] => Array
(
[Product] => Array
(
[cat_id] => 9
[subcat_id] => 3
)
)
[7] => Array
(
[Product] => Array
(
[Subcat] => change
)
)
)
Is this possible.
How about:
$Array = Array(
0 => Array(
'Product' => Array(
'cat_id' => 7,
'subcat_id' => 1,
)
),
1 => Array(
'Product' => Array(
'cat_id' => 7,
'subcat_id' => 1,
)
),
2 => Array(
'Product' => Array(
'cat_id' => 8,
'subcat_id' => 2,
)
),
);
$prev_id = $Array[0]['Product']['subcat_id'];
$result = array(0 => $Array[0]);
for($i = 1; $i < count($Array); $i++) {
if ($Array[$i]['Product']['subcat_id'] != $prev_id) {
$result[]['Product']['subcat'] = 'change';
}
$result[] = $Array[$i];
$prev_id = $Array[$i]['Product']['subcat_id'];
}
$result[]['Product']['subcat'] = 'change';
print_r($result);
Output:
Array
(
[0] => Array
(
[Product] => Array
(
[cat_id] => 7
[subcat_id] => 1
)
)
[1] => Array
(
[Product] => Array
(
[cat_id] => 7
[subcat_id] => 1
)
)
[2] => Array
(
[Product] => Array
(
[subcat] => change
)
)
[3] => Array
(
[Product] => Array
(
[cat_id] => 8
[subcat_id] => 2
)
)
[4] => Array
(
[Product] => Array
(
[subcat] => change
)
)
)
save previous cat_id and subcat_id, check when cat_id added one. This suppose you cat_id is in sequence, added 0 or 1 each step.
$preValue = array('cat_id' => 0, 'subcat_id' => 0);
$changed = false;
foreach ($Array as $item) {
$product = $item['Product'];
if($preValue['cat_id'] != 0 && $product['cat_id'] == $preValue['cat_id'] + 1 && $product['subcat_id'] != $preValue['subcat_id'])
{
$changed = true;
break;
}
$preValue['cat_id'] = $product['cat_id'];
$preValue['subcat_id'] = $product['subcat_id'];
}
This will do what you are looking for:
$old_subcat_id = null;
$newArray = Array();
foreach ($Array as $item) {
$subcat_id = $item['Product']['subcat_id'];
if ($subcat_id != $old_subcat_id) {
//do something here
echo "subcat_id has changed from [$old_subcat_id] to [$subcat_id]<br>";
if ($old_subcat_id != null) {
$newArray[]['Product']['Subcat'] = 'change';
}
$old_subcat_id = $subcat_id;
}
$newArray[] = $item;
}

array one format to another

I have one array in two format. I want to change array from
Array
(
[step_number] => 4
[app_id] => Array
(
[0] => 2
[1] => 3
)
[formdata] => Array
(
[0] => Array
(
[name] => app_id[]
[value] => 2
)
[1] => Array
(
[name] => app_id[]
[value] => 3
)
[2] => Array
(
[name] => fieldval[2][2][]
[value] => 1
)
[3] => Array
(
[name] => fieldval[3][3][]
[value] => 200
)
[4] => Array
(
[name] => fieldval[3][3][]
[value] => day
)
[5] => Array
(
[name] => title
[value] => new plan
)
[6] => Array
(
[name] => feature_plan
[value] => 3
)
[7] => Array
(
[name] => plan_type
[value] => free
)
[8] => Array
(
[name] => price
[value] =>
)
[9] => Array
(
[name] => sell_type
[value] => us
)
)
)
this format to
Array
(
[app_id] => Array
(
[0] => 2
[1] => 3
)
[fieldval] => Array
(
[2] => Array
(
[2] => Array
(
[0] => 1
)
)
[3] => Array
(
[3] => Array
(
[0] => 200
[1] => day
)
)
)
[title] => new plan
[feature_plan] => 3
[plan_type] => free
[price] =>
[sell_type] => us
)
these are are one array into two format. i have data in to first array format and i want to change that format to second array type format.
please tell me how i am trying this for 2 days but not succeed.
Here is a function you could use to produce that conversion:
function convert_formdata($input) {
$output = array();
foreach($input['formdata'] as $data) {
$keys = preg_split("#[\[\]]+#", $data['name']);
$value = $data['value'];
$target = &$output;
foreach($keys as $key) {
// Get index for "[]" reference
if ($key == '') $key = count($target);
// Create the key in the parent array if not there yet
if (!isset($target[$key])) $target[$key] = array();
// Move pointer one level down the hierarchy
$target = &$target[$key];
}
// Write the value at the pointer location
$target = $value;
}
return $output;
}
You would call it like this:
$output = convert_formdata($input);
See it run on eval.in for the given input. The output is:
array (
'app_id' =>
array (
0 => 2,
1 => 3,
),
'fieldval' =>
array (
2 =>
array (
2 =>
array (
0 => 1,
),
),
3 =>
array (
3 =>
array (
0 => 200,
1 => 'day',
),
),
),
'title' => 'new plan,',
'feature_plan' => 3,
'plan_type' => 'free',
'price' => NULL,
'sell_type' => 'us',
)

PHP multidimensional array, average of duplicate values

I'm trying to insert high level product review data to SKU records but am stuck with trying to get the average value of duplicated keys.
Array
(
[0] => Array
(
[sku] => 70835
[rating] => 5
)
[1] => Array
(
[sku] => F6W/35
[rating] => 5
)
[2] => Array
(
[sku] => 36865
[rating] => 5
)
[3] => Array
(
[sku] => 36835
[rating] => 5
)
[4] => Array
(
[sku] => F30W/T8/830/POLYLUX
[rating] => 2
)
[5] => Array
(
[sku] => 70835
[rating] => 4
)
)
I would like to get the average rating for the duplicate skus so expected output would be:
Array
(
[0] => Array
(
[sku] => 70835
[rating] => 4.5
)
[1] => Array
(
[sku] => F6W/35
[rating] => 5
)
[2] => Array
(
[sku] => 36865
[rating] => 5
)
[3] => Array
(
[sku] => 36835
[rating] => 5
)
...
)
I have the below loop which is summing the duplicates but I'm struggling to get the average
foreach ($reviews as $val) {
if (!isset($result[$val['sku']]))
{
$result[$val['sku']] = $val;
}
else{
$result[$val['sku']]['rating'] += $val['rating'];
#This will sum the duplicated ratings but I need to divide the sum here by the number of times the 'sku' index was duplicated so in the example 9/2 = 4.5
}
}
thanks in advance!
What about adding a count field to your result array...
foreach ($reviews as $val) {
if (!isset($result[$val['sku']]))
{
$result[$val['sku']] = $val;
$result[$val['sku']]["count"] = 1;
}
else{
$result[$val['sku']]['rating'] += $val['rating'];
$result[$val['sku']]["count"] ++;
}
}
foreach($result as $k => $v) {
$result[$k]['avg'] = $v['rating']/$v['count'];
}
This should work for you:
foreach ($reviews as $val) {
if (!isset($result[$val['sku']]))
{
$result[$val['sku']] = array('rating' => $val['rating'], 'count' => 1);
}
else{
$result[$val['sku']]['rating'] += $val['rating'];
$result[$val['sku']]['count']++;
}
}
foreach ($result as &$val) {
$val['average'] = $val['rating'] / $val['count'];
}
Be aware, if this data is coming from a database, there are much easier ways to do this, by using GROUP BY statements.
[akshay#localhost tmp]$ cat test.php
<?php
$array = array (
0 =>
array (
'sku' => '70835',
'rating' => '5',
),
1 =>
array (
'sku' => 'F6W/35',
'rating' => '5',
),
2 =>
array (
'sku' => '36865',
'rating' => '5',
),
3 =>
array (
'sku' => '36835',
'rating' => '5',
),
4 =>
array (
'sku' => 'F30W/T8/830/POLYLUX',
'rating' => '2',
),
5 =>
array (
'sku' => '70835',
'rating' => '4',
),
);
$final=$count=array();
foreach($array as $v)
{
if(isset($final[$v['sku']]))
{
$final[$v['sku']]['rating'] += $v['rating'];
$count[$v['sku']]++;
}else
{
$final[$v['sku']] = $v;
$count[$v['sku']] = 1;
}
}
array_map( function($a, $b) use (&$final){ $final[$a]['rating']/=$b; }, array_keys($count),array_values($count));
unset($count);
// Input
print_r($array);
// Output
print_r( array_values($final));
?>
Output
[akshay#localhost tmp]$ php test.php
Array
(
[0] => Array
(
[sku] => 70835
[rating] => 5
)
[1] => Array
(
[sku] => F6W/35
[rating] => 5
)
[2] => Array
(
[sku] => 36865
[rating] => 5
)
[3] => Array
(
[sku] => 36835
[rating] => 5
)
[4] => Array
(
[sku] => F30W/T8/830/POLYLUX
[rating] => 2
)
[5] => Array
(
[sku] => 70835
[rating] => 4
)
)
Array
(
[0] => Array
(
[sku] => 70835
[rating] => 4.5
)
[1] => Array
(
[sku] => F6W/35
[rating] => 5
)
[2] => Array
(
[sku] => 36865
[rating] => 5
)
[3] => Array
(
[sku] => 36835
[rating] => 5
)
[4] => Array
(
[sku] => F30W/T8/830/POLYLUX
[rating] => 2
)
)

PHP Array sorting by parent

I got a complex array to be sorted, it looks like this:
Array
(
[0] => Array
(
[id] => 1171409310
[parent] => 1171287657
[createdAt] => 2013-12-20T12:42:19
)
[1] => Array
(
[id] => 1171360372
[parent] => 1171313704
[createdAt] => 2013-12-20T11:18:46
)
[2] => Array
(
[id] => 1171313704
[parent] => 1171304353
[createdAt] => 2013-12-20T10:14:46
)
[3] => Array
(
[id] => 1171304353
[parent] => 1171287657
[createdAt] => 2013-12-20T09:55:34
)
[4] => Array
(
[id] => 1171303539
[parent] => 1171014482
[createdAt] => 2013-12-20T09:53:54
)
[5] => Array
(
[id] => 1171287657
[parent] => 1170597579
[createdAt] => 2013-12-20T09:29:34
)
[6] => Array
(
[id] => 1171264520
[parent] => 1169354287
[createdAt] => 2013-12-20T08:58:26
)
[7] => Array
(
[id] => 1171014482
[parent] =>
[createdAt] => 2013-12-20T02:51:24
)
[8] => Array
(
[id] => 1170700661
[parent] => 1170597579
[createdAt] => 2013-12-19T21:30:31
)
[9] => Array
(
[id] => 1170597579
[parent] =>
[createdAt] => 2013-12-19T20:22:40
)
[10] => Array
(
[id] => 1169362457
[parent] =>
[createdAt] => 2013-12-18T22:27:28
)
[11] => Array
(
[id] => 1169354287
[parent] =>
[createdAt] => 2013-12-18T22:20:08
)
[12] => Array
(
[id] => 1169315244
[parent] =>
[createdAt] => 2013-12-18T21:52:59
)
)
I want the array to be first sorted by date (oldest on the top) and then each child after its parent (oldest on the top as well). The problem is that children can also be parents who have children as well so there are multiple dimensions. If possible I want also add the dimension.
I hope that my problem is clear.
EDIT: I get the array from the disqus API and want it to be sorted like it is on a website.
EDIT: It has to end like this:
Array
(
[12] => Array
(
[id] => 1169315244
[parent] =>
[createdAt] => 2013-12-18T21:52:59
)
[11] => Array
(
[id] => 1169354287
[parent] =>
[createdAt] => 2013-12-18T22:20:08
)
[6] => Array
(
[id] => 1171264520
[parent] => 1169354287
[createdAt] => 2013-12-20T08:58:26
)
[10] => Array
(
[id] => 1169362457
[parent] =>
[createdAt] => 2013-12-18T22:27:28
)
[9] => Array
(
[id] => 1170597579
[parent] =>
[createdAt] => 2013-12-19T20:22:40
)
[8] => Array
(
[id] => 1170700661
[parent] => 1170597579
[createdAt] => 2013-12-19T21:30:31
)
[5] => Array
(
[id] => 1171287657
[parent] => 1170597579
[createdAt] => 2013-12-20T09:29:34
)
[3] => Array
(
[id] => 1171304353
[parent] => 1171287657
[createdAt] => 2013-12-20T09:55:34
)
[2] => Array
(
[id] => 1171313704
[parent] => 1171304353
[createdAt] => 2013-12-20T10:14:46
)
[1] => Array
(
[id] => 1171360372
[parent] => 1171313704
[createdAt] => 2013-12-20T11:18:46
)
[0] => Array
(
[id] => 1171409310
[parent] => 1171287657
[createdAt] => 2013-12-20T12:42:19
)
[7] => Array
(
[id] => 1171014482
[parent] =>
[createdAt] => 2013-12-20T02:51:24
)
[4] => Array
(
[id] => 1171303539
[parent] => 1171014482
[createdAt] => 2013-12-20T09:53:54
)
)
I'm building a comment system myself, currently. Just ordering the comments like this is not going to really give you a strong relationship between comments (a parent-child relationship).
In this case, I'd do the following:
$comments = array();
foreach ($results as $result) {
if ($result["parent"]) {
$result["children"] = array();
$comments[$result["id"]] = $result;
}
}
// Have yet to do this a better way. Second loop is there for a reason.
foreach ($results as $result) {
if ($result["parent"])
$comments[$result["parent"]]["children"] = $result;
}
var_dump($comments);
// you can now sort on createdAt using uasort(array $array, callable $func)
uasort($comments, function ($a, $b) {
if ($a["createdAt"] == $b["createdAt"])
return 0;
return ($a["createdAt"] > $b["createdAt"]) ? 1 : -1;
// reverse this to change sort order
});
uasort($array, function($a, $b) {
// sort by date first
if (#$a["createdAt"] == #$b["createdAt"]){
return 0;
}
return (#$a["createdAt"] > #$b["createdAt"]) ? 1 : -1;
});
$array_asc = array();
foreach($array as $key => $val){
// create an array with ids as keys and children
// with the assumption that parents are created earlier.
// store the original key
$array_asc[$val['id']] = array_merge($val, array('org_key' => $key));
if ($val['parent']){
$array_asc[$val['parent']]['children'][] = $val['id'];
}
}
$array_out = array();
// get a flat array again
foreach($array_asc as $val){
if ($val['parent']){
continue;
}
add_to_output($array_out, $val, $array_asc);
}
function add_to_output(&$array_out, $val, $array_asc){
$array_out[$val['org_key']] = $val;
if (sizeof($val['children'])){
foreach($val['children'] as $id){
add_to_output($array_out, $array_asc[$id], $array_asc);
}
}
unset($array_out[$val['org_key']]['children'], $array_out[$val['org_key']]['org_key']);
}
not tested.
you can user the php array_multisort
you probably want to build your array like this
<?php
function array_orderby()
{
$args = func_get_args();
$data = array_shift($args);
foreach ($args as $n => $field) {
if (is_string($field)) {
$tmp = array();
foreach ($data as $key => $row)
$tmp[$key] = $row[$field];
$args[$n] = $tmp;
}
}
$args[] = &$data;
call_user_func_array('array_multisort', $args);
return array_pop($args);
}
?>
<?php
$data[] = array('createdAt' => 67, 'parent' => 2);
$data[] = array('createdAt' => 86, 'parent' => 1);
$data[] = array('createdAt' => 85, 'parent' => 6);
$data[] = array('createdAt' => 98, 'parent' => 2);
$data[] = array('createdAt' => 86, 'parent' => 6);
$data[] = array('createdAt' => 67, 'parent' => 7);
// Pass the array, followed by the column names and sort flags
$sorted = array_orderby($name_of_array, 'createdAt', SORT_DESC, 'parent', SORT_ASC);
?>

Array filteration PHP

I have an array with values like:
Array
(
[0] => Array
(
[parent] => Basic
[parentId] => 1
[child] => Birthday
[childId] => 2
)
[1] => Array
(
[parent] => Basic
[parentId] => 1
[child] => Gender
[childId] => 3
)
[2] => Array
(
[parent] => Geo
[parentId] => 10
[child] => Current City
[childId] => 11
)
[3] => Array
(
[parent] => Known me
[parentId] => 5
[child] => My personality
[childId] => 7
)
[4] => Array
(
[parent] => Known me
[parentId] => 5
[child] => Best life moment
[childId] => 8
)
)
And I want to filter this array such that their filtration based on parent index, and the final result would be like:
Array
(
[0] => Array
(
[parent] => Basic
[parentId] => 1
[child] => Array
(
[0] => Birthday
[1] => Gender
)
)
[1] => Array
(
[parent] => Geo
[parentId] => 10
[child] => Array
(
[0] => Current City
)
)
[2] => Array
(
[parent] => Known me
[parentId] => 5
[child] => Array
(
[0] => My personality
[1] => Best life moment
)
)
)
For that I coded :
$filter = array();
$f = 0;
for ($i=0; $i<count($menuArray); $i++) {
$c = 0;
for( $b = 0; $b < count($filter); $b++ ){
if( $filter[$b]['parent'] == $menuArray[$i]['parent'] ){
$c++;
}
}
if ($c == 0) {
$filter[$f]['parent'] = $menuArray[$i]['parent'];
$filter[$f]['parentId'] = $menuArray[$i]['parentId'];
$filter[$f]['child'][] = $menuArray[$i]['child'];
$f++;
}
}
But it results :
Array
(
[0] => Array
(
[parent] => Basic
[parentId] => 1
[child] => Array
(
[0] => Birthday
)
)
[1] => Array
(
[parent] => Geo
[parentId] => 10
[child] => Array
(
[0] => Current City
)
)
[2] => Array
(
[parent] => Known me
[parentId] => 5
[child] => Array
(
[0] => My personality
)
)
)
Could anyone point out my missing LOC?
Try:
$filter = array();
foreach ($menuArray as $menu) {
if (!array_key_exists($menu['parent_id'], $filter)) {
$filter[$menu['parent_id']] = array(
'parent' => $menu['parent'],
'parent_id' => $menu['parent_id'],
'child' => array()
);
}
$filter[$menu['parent_id']]['child'][$menu['child_id']] = $menu['child'];
}
This will produce an array like:
Array
(
[1] => Array
(
[parent] => Basic
[parentId] => 1
[child] => Array
(
[2] => Birthday
[3] => Gender
)
)
[10] => Array
(
[parent] => Geo
[parentId] => 10
[child] => Array
(
[11] => Current City
)
)
[5] => Array
(
[parent] => Known me
[parentId] => 5
[child] => Array
(
[7] => My personality
[8] => Best life moment
)
)
)
Notice that the array indexes match the IDs. You can't loop this with a for loop but you can foreach ($filter as $parent_id=>$parent) correctly. If you want to you can change line 4 of my code to $filter['key_' . $menu['parent_id']] to force a string and a for loop will work
The next piece of code is completely untested, and based on the idea that it's sorted by parentId.
$filter = array();
$option = null;
for( $i = 0; $i < count( $menuArray ); $i++ ) {
if( count( $filter ) < 1 || $filter[count($filter)-1]['parentId'] != $menuArray['parentId'] ) {
if( $option != null ) {
$filter[] = $option;
}
$option = array(
"parent" => $menuArray[$i]['parent'],
"parentId" => $menuArray[$i]['parentId'],
"child" => array()
);
}
$option['child'][] = $menuArray[$i]['child'];
}
$filter[] = $option; // one last time, because we left the loop already.
unset( $option ); // we don't need it anymore.
What it does, it creates a $option for every parent. As soon as we hit the next parentId we add the current $option to the $filter array and create a new $option object.
All the children just keep getting added to the current $option.

Categories