How to control the depth of php infinite pole classification - php

Here is my array:
$list = array(
array('id' => 3, 'name' => 'Phones', 'parent_id' => 0,),
array('id' => 256, 'name' => 'Accessories', 'parent_id' => 0,),
array('id' => 308, 'name' => 'Appliances', 'parent_id' => 0,),
array('id' => 1057, 'name' => 'Smart', 'parent_id' => 0,),
array('id' => 1065, 'name' => 'Smart Phones', 'parent_id' => 3,),
array('id' => 1066, 'name' => 'Feature Phones', 'parent_id' => 3,),
array('id' => 1069, 'name' => 'Samsung', 'parent_id' => 1065,),
array('id' => 1070, 'name' => 'Apple', 'parent_id' => 1065,),
array('id' => 1072, 'name' => 'Apple', 'parent_id' => 1066,),
array('id' => 1075, 'name' => 'Tablets', 'parent_id' => 0,),
array('id' => 1076, 'name' => 'Samsung', 'parent_id' => 1066,),
array('id' => 1077, 'name' => 'All Brands', 'parent_id' => 1075,),
array('id' => 1078, 'name' => 'Samsung', 'parent_id' => 1077,),
array('id' => 1079, 'name' => 'Protector', 'parent_id' => 256,),
array('id' => 1080, 'name' => 'Power', 'parent_id' => 256,),
array('id' => 1081, 'name' => 'Cable', 'parent_id' => 256,),
array('id' => 1082, 'name' => 'Memory', 'parent_id' => 256,),
);
This is the code I categorized:
function quote_make_tree($list,$deep=1, $root = 0)
{
$tree = $packData = [];
foreach ($list as $row) {
$packData[$row['id']] = $row;
}
foreach ($packData as $key => $val) {
if ($val['parent_id'] == $root) {
$tree[] = &$packData[$key];
} else {
$packData[$val['parent_id']]['children'][] = &$packData[$key];
}
}
return $tree;
}
I want to add a deep parameter $deep to quote_make_tree to control the depth of classification.
The result I want:
If $deep = 1 Get only data with parent_id = 0:
$one = array(
0 => array('id' => 3, 'name' => 'Phones', 'parent_id' => 0,),
1 => array('id' => 256, 'name' => 'Accessories', 'parent_id' => 0,),
2 => array('id' => 308, 'name' => 'Appliances', 'parent_id' => 0,),
3 => array('id' => 1057, 'name' => 'Smart', 'parent_id' => 0,),
4 => array('id' => 1075, 'name' => 'Tablets', 'parent_id' => 0,),
);
If $deep = 2,Get level 2 classification below level 1 classification,if $deep=3,Get all 1,2,3 classifications
I have tried get all the data first, then delete the data according to $deep.here is demo,thanks folks

This might be easier to solve using a recursive method. This allows you to check the depth and if you want more details then it will call itself to add in more layers. Each time calling itself you just take one off the depth...
function quote_make_tree($list, $deep=1, $root = 0) {
$output = [];
foreach ( $list as $listItem ) {
if ( $listItem['parent_id'] == $root ) {
if ( $deep > 1 ) {
$listItem['children'] = quote_make_tree($list, $deep-1, $listItem['id']);
}
$output[] = $listItem;
}
}
return $output;
}

Related

Get simple recursive from table with id_parent

I guess my brain starts to slow down, but I want to get a recursive array of my results from this table :
|id|int(11)|
|name|varchar(150)|
|type|tinyint(4)|
|id_parent|mediumint(9)|
|1|Marque forte|1|0|
|2|Communication|2|1|
|3|Respect du CI|0|2|
|4|Stratégie digitale|0|2
|5|Expérience de marque|2|1|
|6|Gastronomie|0|5|
I want an array like :
array('id' => array('name' => $name, 'childs' => array( ... ), 'id' => ...)
I just want to order my dataset in one array.
I tried this so far :
// returns array of objects - codeigniter result
$dbResult = $this->db->get_where('table')->result();
// will contains the array
$this->data['tree'] = array();
$this->getRecursive(0, 0, $dbResult);
....
private function getRecursive($parent, $niveau, $result)
{
foreach ($result AS $row)
{
if ($parent == $row->id_parent)
{
$this->data['tree'][] = array($row->name => $this->getRecursive($row->id, ($niveau + 1), $result));
}
}
}
Which gives me weird result ...
Please try this. I have used the $source array for testing. Since I did not get my result set from an actual database, you will have to make some changes in order to adjust it with your code (eg. change $row['id_parent'] to $row->id_parent and so on). However, conceptually it should work.
<?php
$source = [
['name' => 'A', 'id' => 1, 'id_parent' => 0],
['name' => 'B', 'id' => 2, 'id_parent' => 1],
['name' => 'C', 'id' => 3, 'id_parent' => 1],
['name' => 'D', 'id' => 4, 'id_parent' => 2],
['name' => 'E', 'id' => 5, 'id_parent' => 3],
['name' => 'F', 'id' => 5, 'id_parent' => 0],
];
function getRecursive($source, $parent) {
$result = [];
foreach ($source as $row) {
if ($parent == $row['id_parent']) {
$result[] = [
'id' => $row['id'],
'name' => $row['name'],
'childs' => getRecursive($source, $row['id'] )
];
}
}
return $result;
}
print_r(getRecursive($source, 0));
You don't need a recursion here - the following should do the job
$arrTreeById = [];
//$arrData = $this->db->get_where('table')->result_array();
$arrData = [
[
'id' => 1,
'name' => 'Marque forte',
'type' => 2,
'id_parent' => 0
],
[
'id' => 2,
'name' => 'Communication',
'type' => 2,
'id_parent' => 1
],
[
'id' => 3,
'name' => 'Respect du CI',
'type' => 0,
'id_parent' => 2
],
[
'id' => 4,
'name' => 'Stratégie digitale',
'type' => 0,
'id_parent' => 2
],
[
'id' => 5,
'name' => 'Expérience de marque',
'type' => 2,
'id_parent' => 1
],
[
'id' => 6,
'name' => 'Gastronomie',
'type' => 0,
'id_parent' => 5
],
];
foreach($arrData AS $arrItem)
{
$arrTreeById[$arrItem['id']] = $arrItem;
}
foreach($arrTreeById AS &$arrItem)
{
if (isset($arrTreeById[$arrItem['id_parent']]))
{
$arrTreeById[$arrItem['id_parent']]['arrChilds'][] = &$arrItem;
}
if ($arrItem['id_parent'] == 0) $intStartingKey = $arrItem['id'];
}
print_r($arrTreeById[$intStartingKey]);

Multidimensional array difference

I need find difference between multidimensional arrays
I have arrays like this :
$arr1 = array(
'test1' => array(
'XXX' => array(
'w1' => array('id' => '5'),
'w2' => array('id' => '2'),
'w3' => array('id' => 'g'),
),
'YYY' => array(
'w1' => array('id' => '4'),
'w2' => array('id' => '1')
),
'ZZZ' => array(
'w1' => array('id' => '3'),
'w2' => array('id' => '9')
),
'QQQ' => array(
'w1' => array('id' => '3'),
'w2' => array('id' => '9')
),
),
'test2' => array(
'XXX' => array(
'w1' => array('id' => '8'),
'w2' => array('id' => '3')
),
'YYY' => array(
'w1' => array('id' => '15'),
'w2' => array('id' => '1')
),
'ZZZ' => array(
'w1' => array('id' => '5'),
'w2' => array('id' => '2')
),
),
);
$arr2 = array(
'test1' => array(
'XXX' => array(
'w1' => array('id' => '5'),
'w2' => array('id' => '2'),
'w3' => array('id' => 'g'),
'w4' => array('id' => 'x'),
),
'YYY' => array(
'w1' => array('id' => '4'),
'w2' => array('id' => '1')
),
'ZZZ' => array(
'w1' => array('id' => '3'),
'w2' => array('id' => '9')
),
),
);
And I need to remove duplicates but I need compare first level key, second level key and last level key,value pairs so my results should be like that
array(
'test1' => array(
'XXX' => array(
'w4' => array('id' => 'x'),
),
)
I try use
function check_key($a,$b) {
if ($a===$b)
{
return 0;
}
return ($a>$b)?1:-1;
}
function check_value($a,$b) {
if ($a===$b)
{
return 0;
}
return ($a>$b)?1:-1;
}
$merged_arr = array_udiff_uassoc($arr2,$arr1,"check_key","check_value");
But this function don't compare last level key-value pair in last level .
Try with this function.I think It will be helpful to you.
$result[] = array_diff_key($arr1, $arr2);
print_r($result);

How can I make a binary tree array from the array?

I have the array of persons:
array(
array(
'name' => 'John',
'id' => 1,
'mother_id' => 2,
'father_id' => 3
),
array(
'name' => 'Lucy',
'id' => 2,
'mother_id' => 5,
'father_id' => 4
),
array(
'name' => 'Jim',
'id' => 3,
'mother_id' => 7,
'father_id' => 9
),
array(
'name' => 'Paul',
'id' => 4,
'mother_id' => 534,
'father_id' => 54
),
array(
'name' => 'Laura',
'id' => 5,
'mother_id' => 554,
'father_id' => 51
),
array(
'name' => 'Vanessa',
'id' => 7,
'mother_id' => 5354,
'father_id' => 514
),
array(
'name' => 'Adam',
'id' => 9,
'mother_id' => 245354,
'father_id' => 514234
),
);
And I want to get this:
array(
array(
'person' => array(
'name' => 'John',
'id' => 1,
'mother_id' => 2,
'father_id' => 3
),
'parents' => array(
'mother' => array(
'person' => array(
'name' => 'Lucy',
'id' => 2,
'mother_id' => 5,
'father_id' => 4
),
'parents' => array(
'mother' => array(
'person' => array(
'name' => 'Laura',
'id' => 5,
'mother_id' => 554,
'father_id' => 51
),
'parents' => array(...)
),
'father' => array(
'person' => array(
'name' => 'Paul',
'id' => 4,
'mother_id' => 534,
'father_id' => 54
),
'parents' => array(...)
),
)
),
'father' => ...
)
So John is a child that has mother and father, father has mother and father, mother has mother and father and etc, and write a script that do something but not what I want exactly
function parseTree(& $tree, $root = null) {
$return = null;
foreach ($tree as $key=> $item){
if ($item['id'] == $root){
$return = [
'person' => $item,
'parents' => [
'father' => parseTree($tree, $item['father_id'])
]
];
unset ($tree[$key]);
}elseif($item['id'] == $root){
$return = [
'person' => $item,
'parents' => [
'father' => parseTree($tree, $item['mother_id'])
]
];
unset ($tree[$key]);
}
elseif ($root == null) {
$return = [
'person' => $item,
'parents' => [
'father' => parseTree($tree, $item['father_id']),
'mother' => parseTree($tree, $item['mother_id'])
]
];
unset ($tree[$key]);
}
}
return $return;
}
How can I make it work? Or maybe there are some proper libraries for that?
You almost had it. I would do it in this manner:
function parseTree(&$tree, $root = null)
{
$return = null;
foreach ($tree as $key => $item) {
if ($root == null || $item['id'] == $root) {
$return = [
'person' => $item,
'parents' => [
'father' => parseTree($tree, $item['father_id']),
'mother' => parseTree($tree, $item['mother_id'])
]
];
unset ($tree[$key]);
}
}
return $return;
}

search within array PHP

I have an array which contains some data. for example ---
$data = array(
'CATEGORY 1' => array(
array('id'=> 0, 'name' => 'John', 'category' => 'CATEGORY1'),
array('id'=> 1, 'name' => 'Jack', 'category' => 'CATEGORY1'),
array('id'=> 2, 'name' => 'Jame', 'category' => 'CATEGORY1'),
),
'CATEGORY 2' => array(
array('id'=> 0, 'name' => 'Mile', 'category' => 'CATEGORY2'),
array('id'=> 1, 'name' => 'Mike', 'category' => 'CATEGORY2'),
array('id'=> 2, 'name' => 'Matt', 'category' => 'CATEGORY2'),
)
);
Now how can i write a function like this ---
if ($post ='CATEGORY 1') {
// filter all the name where category => CATEGORY1
}
expected output --
'John', 'Jack', 'Jame';
i have tried like so ---
$filters = array
(
"id" => array
(
"filter" => FILTER_VALIDATE_INT,
"flags" => FILTER_FORCE_ARRAY,
"options" => array
(
"min_range" => 1,
"max_range" => 120
)
),
"name" => array
(
"filter" => FILTER_CALLBACK,
"options" => "ucwords"
),
"category" => array
(
"filter" => FILTER_CALLBACK,
"options" => "ucwords"
)
);
print_r(filter_var_array($data, $filters));
but that returns me null, how can i search within the array with the condition where category is category1 fetch all the names belongs to that ...
i know it can be a really dumb question, but people sometime get stuck on a really basic problem.
Hope someone knows the answer.
<?php
$data = array(
'CATEGORY 1' => array(
array('id'=> 0, 'name' => 'John', 'category' => 'CATEGORY1'),
array('id'=> 1, 'name' => 'Jack', 'category' => 'CATEGORY1'),
array('id'=> 2, 'name' => 'Jame', 'category' => 'CATEGORY1'),
),
'CATEGORY 2' => array(
array('id'=> 0, 'name' => 'Mile', 'category' => 'CATEGORY2'),
array('id'=> 1, 'name' => 'Mike', 'category' => 'CATEGORY2'),
array('id'=> 2, 'name' => 'Matt', 'category' => 'CATEGORY2'),
)
);
$post = 'CATEGORY 1';
$pluck = 'name';
var_dump( array_reduce($data['CATEGORY 1'], function($result, $array) use ( $pluck ) {
isset($array[$pluck]) && $result[] = $array[$pluck];
return $result;
}, array()));
Simply use foreach like as
$result = [];
foreach($data as $value){
foreach($value as $k => $v){
if($v['category'] == 'CATEGORY1')
$result[] = $v['name'];
}
}
print_r($result);
Demo
Bellow code will help you out
<?php
$data = array(
'CATEGORY 1' => array(
array('id'=> 0, 'name' => 'John', 'category' => 'CATEGORY1'),
array('id'=> 1, 'name' => 'Jack', 'category' => 'CATEGORY1'),
array('id'=> 2, 'name' => 'Jame', 'category' => 'CATEGORY1'),
),
'CATEGORY 2' => array(
array('id'=> 0, 'name' => 'Mile', 'category' => 'CATEGORY2'),
array('id'=> 1, 'name' => 'Mike', 'category' => 'CATEGORY2'),
array('id'=> 2, 'name' => 'Matt', 'category' => 'CATEGORY2'),
)
);
$post='CATEGORY 1';
$elements=$data[$post];
$names=array();
foreach ($elements as $ele) {
$names[]=$ele['name'];
}
print_r($names);
click here get realtime output

Fastest way to format SQL results in PHP

What's the fastest (best performing) way in PHP to transform a (My)SQL result like:
array(
array('user_name' => 'john', 'tag_id' => 1, 'tag_name' => 'foo'),
array('user_name' => 'john', 'tag_id' => 2, 'tag_name' => 'bar'),
array('user_name' => 'rick', 'tag_id' => 3, 'tag_name' => 'foobar'),
array('user_name' => 'rick', 'tag_id' => 2, 'tag_name' => 'bar')
);
Into the easier to use:
array(
array('name' => 'john', 'tags' => array(
array('id' => 1, 'name' => 'foo'),
array('id' => 2, 'name' => 'bar')
),
array('name' => 'rick', 'tags' => array(
array('id' => 3, 'name' => 'foobar'),
array('id' => 2, 'name' => 'bar')
)
);
Or is there a library that does this already, without the added inflexibility and performance hit of full ORM?
Thanks
Try this:
$data = array(
array('user_name' => 'john', 'tag_id' => 1, 'tag_name' => 'foo'),
array('user_name' => 'john', 'tag_id' => 2, 'tag_name' => 'bar'),
array('user_name' => 'rick', 'tag_id' => 3, 'tag_name' => 'foobar'),
array('user_name' => 'rick', 'tag_id' => 2, 'tag_name' => 'bar')
);
$final = array();
foreach ($data as $item) {
if (!isset($final[$item['user_name']])) {
$final[$item['user_name']] = array(
'name' => $item['user_name'],
'tags' => array()
);
}
$final[$item['user_name']]['tags'][] = array(
'id' => $item['tag_id'],
'name' => $item['tag_name']
);
}
$final = array_values($final);
ezSQL at http://www.woyano.com/jv/ezsql should do what you want. I've taken over a project that uses it and it appear quite nicely put together. Myself I prefer to be somewhat closer to the metal, but if you wish to abstract away then it appears pretty solid in my experience.

Categories