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.
Related
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;
}
Hello good morning wherever you are :D, i have a lil problem, i have this code of arrays
$arrayToView is the info of every single user that i want.
$tagsArray are only tags that use every user but i need to merge all the info something like the last array...
$arrayToView = array(
'IVOFACUNDO' = array(
'mails' => 3,
'contacts' => 34,
'blocked' => 23
),
'ESRAYCU' = array(
'mails' => 23,
'contacts' => 124,
'blocked' => 44
)
)
And i have another one like this
$tagsArray= array(
'IVOFACUNDO' = array(
'14' => array(
'id' => 14,
'name' => 'php',
'value' => 1
),
'15' => array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
),
'ESRAYCU' = array(
'1' => array(
'id' => 1,
'name' => 'python',
'value' => 1
),
'15'=> array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
)
so the question is how i can merge both arrays obviously respectively with the same admin something like this
$arrayToView = array(
'IVOFACUNDO' = array(
'mails' => 3,
'contacts' => 34,
'blocked' => 23,
'tags' => array(
'14' => array(
'id' => 14,
'name' => 'php',
'value' => 1
),
'15' => array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
),
'ESRAYCU' = array(
'mails' => 23,
'contacts' => 124,
'blocked' => 44,
'tags' => array(
'1' => array(
'id' => 1,
'name' => 'python',
'value' => 1
),
'15'=> array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
)
)
The key 'tags' need to be created in the merge of every iteration to add and get one array with all the values, how i can do this?
You can try this snippet.
foreach($arrayToView as $key => $arr){
if(array_key_exists($key, $tagsArray)){
$arrayToView[$key]['tags'] = $tagsArray[$key];
}
}
echo '<pre>';print_r($arrayToView);echo '</pre>';
Use php inbuilt function
$result_Arr = array_merge_recursive($arrayToView,$tagsArray);
<?php
$arrayToView = array(
'IVOFACUNDO' => array(
'mails' => 3,
'contacts' => 34,
'blocked' => 23
),
'ESRAYCU' => array(
'mails' => 23,
'contacts' => 124,
'blocked' => 44
)
);
$tagsArray= array(
'IVOFACUNDO' => array(
'14' => array(
'id' => 14,
'name' => 'php',
'value' => 1
),
'15' => array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
),
'ESRAYCU' => array(
'1' => array(
'id' => 1,
'name' => 'python',
'value' => 1
),
'15'=> array(
'id' => 15,
'name' => 'javascript',
'value' => 1
)
)
);
foreach($arrayToView as $key => $value){
if(isset($tagsArray[$key])){
$arrayToView[$key]['tags'] = array();
foreach($tagsArray[$key] as $key2 => $value2){
$arrayToView[$key]['tags'][$key2] = $tagsArray[$key][$key2];
}
}
}
echo'<pre>';
print_r($arrayToView);
echo'</pre>';
?>
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);
I have a stored unlimited nested levels array with unwanted extra data.
$arr = array(
array(
'name' => 'item1',
'level' => 0,
'extra_key' => 'some_data',
'children' => array(
'name' => 'sub-item1',
'level' => 1,
'extra_key' => 'some_data',
'children' => array(
'name' => 'sub-sub-item1',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
array(
'name' => 'sub-sub2-item1',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
)
),
array(
'name' => 'item2',
'level' => 0,
'extra_key' => 'some_data',
'children' => array(
'name' => 'sub-item2',
'level' => 2,
'extra_key' => 'some_data',
'children' => array(
'name' => 'sub-sub-item2',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
array(
'name' => 'sub-sub2-item2',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
)
),
array(
'name' => 'item3',
'level' => 0,
'extra_key' => 'some_data',
'children' => array(
'name' => 'sub-item3',
'level' => 1,
'extra_key' => 'some_data',
'children' => array(
'name' => 'sub-sub-item3',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
array(
'name' => 'sub-sub2-item3',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
)
),
);
Expected output array:
$arr = array(
array(
'name' => 'item1',
'nodes' => array(
'name' => 'sub-item1',
'nodes' => array(
'name' => 'sub-sub-item1',
'nodes' => array()
),
array(
'name' => 'sub-sub2-item1',
'nodes' => array()
),
)
),
array(
'name' => 'item2',
'nodes' => array(
'name' => 'sub-item2',
'nodes' => array(
'name' => 'sub-sub-item2',
'nodes' => array()
),
array(
'name' => 'sub-sub2-item2',
'nodes' => array()
),
)
),
array(
'name' => 'item3',
'nodes' => array(
'name' => 'sub-item3',
'nodes' => array(
'name' => 'sub-sub-item3',
'nodes' => array()
),
array(
'name' => 'sub-sub2-item3',
'nodes' => array()
),
)
)
);
I want to remove unwanted keys like level , extra_key from all levels and i want also to change the name of the key children to nodes then reproduce the same array with the same structure with the new format.
How can i achieve that?
I tried to do it by recursive function but i failed to reproduce the same structrue
Your structure doesn't make sense, probably because of that you was unable to write recursive function. If it is possible to change structure, I would suggest this one (with reformat function implementation):
<?php
$actual = array(
array(
'name' => 'item1',
'level' => 0,
'extra_key' => 'some_data',
'children' => array(
array(
'name' => 'sub-item1',
'level' => 1,
'extra_key' => 'some_data',
'children' => array(
array(
'name' => 'sub-sub-item1',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
array(
'name' => 'sub-sub2-item1',
'level' => 2,
'extra_key' => 'some_data',
'children' => array()
),
)
),
)
),
);
$expected = array(
array(
'name' => 'item1',
'nodes' => array(
array(
'name' => 'sub-item1',
'nodes' => array(
array(
'name' => 'sub-sub-item1',
'nodes' => array()
),
array(
'name' => 'sub-sub2-item1',
'nodes' => array()
),
),
),
)
),
);
function change_array($original)
{
return array_map('change_node', $original);
}
function change_node($node)
{
return [
'name' => $node['name'],
'nodes' => array_map('change_node', $node['children']),
];
}
var_dump($expected === change_array($actual));
This function will do what you want recursively.
You can add extra excluded and/or renamed indices if required;
function parseArray($array): array
{
// The resulting array
$result = [];
// Indices you want renamed [`from` => `to`]
$renameIndices = ['children' => 'nodes'];
// Indices you want excluded [`1`, `2`]
$excludedIndices = ['level', 'extra_key'];
foreach ($array as $idx => $content)
{
// If excluded, continue (skip) node.
if (in_array($idx, $excludedIndices, true))
{
continue;
}
// Setting the resulting (new) index.
$resultIdx = $idx;
// Check if this index should be renamed
if (array_key_exists($idx, $renameIndices))
{
// If index should be renamed, apply new name
$resultIdx = $renameIndices[$idx];
}
// If this content block is an array. Parse it.
if (is_array($content))
{
$content = parseArray($content);
}
// Save content to resulting array.
$result[$resultIdx] = $content;
}
return $result;
}
Hi I'm have recursion function that makes binary tree array, so from that
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
),
);
I'm getting that:
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' => ...
)
and it works completely fine until it gets array with more than -+100 values, and when it gets this array, it returns 500 error, that's seems strange for me, cos obviously I don't have infinite loop or something like that, cos smallest arrays parses fine but I can't figure out what's reason for this kind of behavior.
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;
}