$list = array(
array(
'header_name' => '1.',
'header_database_name' => '2',
'heading' => 'personal',
),
array(
'header_name' => '11. ',
'header_database_name' => '22',
'heading' => 'professional',
),
array(
'header_name' => '33',
'header_database_name' => '333',
'heading' => 'personal',
),
);
foreach($list as $li)
{
?>
"> ';}
else ($li['heading'] == 'performance')
{echo $li['header_name'].'';}
}
I need to print this array by grouping it by heading for example the one with heading as personal should be displayed under the personal title i.e:
Personal
1
33
Professional
11
my php code is like this
foreach($list as $li)
{
?>
"> ';}
else ($li['heading'] == 'performance')
{echo $li['header_name'].'';}
}
It is printing by group but i also need heading to be added but only one time at the top for example now if i add heading to it it prints as personal 1
professional 2
peronal 3
but i need as
personal
1
2
professional
2
You need to sort array if you want grouping of data, use usort
function headingSort ($x, $y) {
return strcasecmp($x['heading'], $y['heading']);
}
usort($myArray, 'headingSort');
Use like
$new_array = array();
foreach($list as $k=>$v)
{
if(!in_array($v['header_name'], $new_array))
$new_array[$v['heading']][] = $v['header_name'];
else
$new_array[$v['heading']] = $v['header_name'];
}
print_r($new_array);
Try this :
$list = array(
array(
'header_name' => '1.',
'header_database_name' => '2',
'heading' => 'personal',
),
array(
'header_name' => '11. ',
'header_database_name' => '22',
'heading' => 'professional',
),
array(
'header_name' => '33',
'header_database_name' => '333',
'heading' => 'personal',
)
);
$personal = array();
$professional = array();
for($i=0;$i<count($list);$i++){
if($list[$i]['heading']=="professional"){
array_push($professional,$list[$i]);
}else{
array_push($personal,$list[$i]);
}
}
$new = array(
"personal"=>$personal,
"professional"=>$professional
);
echo "<pre>";
print_r($new);
Result will be like :
Array
(
[personal] => Array
(
[0] => Array
(
[header_name] => 1.
[header_database_name] => 2
[heading] => personal
)
[1] => Array
(
[header_name] => 33
[header_database_name] => 333
[heading] => personal
)
)
[professional] => Array
(
[0] => Array
(
[header_name] => 11.
[header_database_name] => 22
[heading] => professional
)
)
)
The solution using array_column(available since PHP 5.5), array_unique, array_keys and implode functions:
$headings = array_column($list, 'heading', 'header_name');
foreach (array_unique($headings) as $v) {
echo ucfirst($v). PHP_EOL;
echo implode("\n", array_keys($headings, $v)). PHP_EOL;
}
The output:
Personal
1
33
Professional
11
Related
I have this tree :
Array
(
[0] => Array
(
[id] => 1
[parent_id] => 0
[title] => Parent Page
[children] => Array
(
[0] => Array
(
[id] => 2
[parent_id] => 1
[title] => Sub Page
),
[1] => Array
(
[id] => 5
[parent_id] => 1
[title] => Sub Page 2
)
)
)
[1] => Array
(
[id] => 4
[parent_id] => 0
[title] => Another Parent Page
)
)
And I'm looking for a display from top to bottom.
And display something like this :
1
1.2
1.5
4
But if I have id 3 which is a leaf from 5 I would like this :
1
1.2
1.5
1.5.3
4
I have search a lot and my brain is limited when i'm using recursivity..
I have tried this :
function printAll($a){
foreach ($a as $v){
if (!array_key_exists('children', $v)){
debugLog($v['id']);
return;
}
else{
$arrayChildrens = $v['children'];
foreach($arrayChildrens as $c){
$arrayChildrens = $c['children'];
$this->printAll($arrayChildrens);
}
}
}
}
But doesn't work..
I tried to begin just to display
1
2
5
4
But my goal is to display id parents before id ( like Ishowed you before)
Thanks a lot !
This function should give you your expected output.
function printAll($a, $prefix = '') {
//loop through $a
foreach($a as $v) {
//echo current level `id` with previous `$prefix`
echo "{$prefix}{$v['id']}\n";
//check if current level contains children
if(!empty($v['children'])) {
//clean up prefix to remove extra `.` at the end of prefixes
$prev_prefix = rtrim($prefix, '.');
//recurse printAll again passing the children as `$a` and a `$prefix` being the previous levels combined e.g `1.5`
//also clean up extra periods at the start of the prefix
printAll($v['children'], ltrim("{$prev_prefix}.{$v['id']}.", "."));
}
}
}
Output:
1
1.2
1.5
1.5.3
4
Using a proper return
Usually with a function you actually want the function to return values instead of echoing them automatically to your page. If you want this function to return an array of values instead of echoing them, you could do this:
function printAll($a, $level = '', $values = []) {
foreach($a as $v) {
$values[] = $value = "{$level}{$v['id']}";
if(!empty($v['children'])) {
$values = printAll($v['children'], "{$value}.", $values);
}
}
return $values;
}
Which will have a result like this:
Array
(
[0] => 1
[1] => 1.2
[2] => 1.5
[3] => 1.5.3
[4] => 4
)
This should do the job.
$arr = array(
array(
'id' => 1,
'parent_id' => 0,
'title' => 'Parent Page',
'children' => array(
array(
'id' => 2,
'parent_id' => 1,
'title' => 'Sub Page',
),
array(
'id' => 5,
'parent_id' => 1,
'title' => 'Sub Page 2',
'children' => array(
array(
'id' => 7,
'parent_id' => 5,
'title' => 'Sub Page',
),
array(
'id' => 8,
'parent_id' => 5,
'title' => 'Sub Page 2',
)
)
)
)
),
array(
'id' => 4,
'parent_id' => 0,
'title' => 'Another Parent Page',
)
);
function printAll($arr, $parent = [])
{
if (is_array($arr)) {
foreach ($arr as $k => $v) {
if (isset($v['id'])) {
$parent[] = $v['id'];
echo implode('.', $parent) . PHP_EOL;
}
if (isset($v['children'])) {
printAll($v['children'], $parent);
}
array_pop($parent);
}
}
}
printAll($arr);
Output
1
1.2
1.5
1.5.7
1.5.8
4
Working demo.
I have a working delivery system that I need to present in alphabetical order sorted by the city, which is the key in a subarray.
This is the array:
array (
'option_3' => array (
'Rio' => '18',
),
'option_4' => array (
'Tokyo' => '20',
),
'option_5' => array (
'Berlim' => '23',
)
)
And it is shown in this table:
<table>
<tr>
<th>ID</th>
<th>Bairro</th>
<th>Valor</th>
<th>Ação</th>
</tr>
[a foreach goes here]
<tr>
<td><?php echo $option_number;?></td>
<td><?php echo $city;?></td>
<td><?php echo $price;?></td>
<td><button type='submit'>Remove</button></td>
</tr>
<table>
This produces the folowing result:
ID City Value Action
3 Rio 18 Remover
4 Tokyo 20 Remover
5 Berlim 23 Remover
But I need it to be sorted by the city:
ID City Value Action
5 Berlim 23 Remover
3 Rio 18 Remover
4 Tokyo 20 Remover
How could I accomplish this?
You need to preserve the outer keys, use uasort(). I prefer the spaceship (3-way comparison) operator between two key() calls.
Code: (Demo)
$options = [
'option_3' => [
'Rio' => '18',
],
'option_4' => [
'Tokyo' => '20',
],
'option_5' => [
'Berlim' => '23',
]
];
uasort($options, function ($a, $b) {
return key($a) <=> key($b);
});
var_export($options);
Output:
array (
'option_5' =>
array (
'Berlim' => '23',
),
'option_3' =>
array (
'Rio' => '18',
),
'option_4' =>
array (
'Tokyo' => '20',
),
)
From PHP7.4+, You can use arrow syntax inside custom functions. (Demo)
uasort($options, fn($a, $b) => key($a) <=> key($b));
Preparing for an array_multisort() call is prohibitively hideous, IMO. (Demo)
array_multisort(array_keys(array_merge(...array_values($options))), $options);
Firstly, create a single array for each city and push them into a new array like that:
$options = [
'option_3' => [
'Rio' => '18',
],
'option_4' => [
'Tokyo' => '20',
],
'option_5' => [
'Berlim' => '23',
]
];
$newOptions = [];
foreach($options as $key => $option) {
array_push($newOptions, [
'id' => $key,
'city' => key($option),
'price' => reset($option)
]);
}
After, just sort it alphabetically by the value of each 'city' using usort()
usort($newOptions, function($a, $b) {
return strcmp($a['city'], $b['city']);
});
Finally, you can simply do a foreach into $newOptions and echo whatever you want based on keys 'id', 'city' and 'price'. Example:
foreach($newOptions as $option)
<tr>
<td><?php echo $option['id'];?></td>
<td><?php echo $option['city']?></td>
<td><?php echo $option['price']?></td>
<td><button type='submit'>Remove</button></td>
</tr>
Ok, this sort is little trickier as we need to preserve the parent key for each city as well. So, we go as follows:
Modify the current array to have an extra parent_key in it's subarray which would look like:
'option_3' => array (
'Rio' => '18',
'parent_key' => 'option_3'
)
Now, we use usort() to compare the 2 subarrays via name through strcmp() and return the result.
We again iterate through them and use array_keys() to iterate over the data set. We do this as we are going to restore the parent key back without running into concurrent modification issue while iterating over the same array.
Code:
<?php
$data = array (
'option_3' => array (
'Rio' => '18',
),
'option_4' => array (
'Tokyo' => '20',
),
'option_5' => array (
'Berlim' => '23',
)
);
foreach($data as $key => &$value){
$value['parent_key'] = $key;
}
usort($data,function($val1,$val2){
$name1 = array_keys($val1)[0];
$name2 = array_keys($val2)[0];
return strcmp($name1,$name2);
});
foreach(array_keys($data) as $index){
$value = $data[$index];
$parent_key = $value['parent_key'];
unset($value['parent_key']); // unset parent key now as it is no longer needed
$data[$parent_key] = $value;
unset($data[$index]); // unset numeric index modified by usort()
}
print_r($data);
Demo: https://3v4l.org/q0YFk
Update: Current result does not hold extra keys like city etc, but it is easy to figure that out as a city name while doing a foreach in key-value fashion.
You can accomplish that in many ways, here is my way Demo, hope it works for you.
$arr = array (
'option_3' => array (
'Rio' => '18',
),
'option_4' => array (
'Tokyo' => '20',
),
'option_5' => array (
'Berlim' => '23',
)
);
$cities = [];
foreach($arr as $key=>$val){
foreach($val as $key2=>$city){
$option = explode('_', $key);
$cities[$key2] = $city.'_'.$option[1];
}
}
ksort($cities);
$res = [];
foreach($cities as $key=>$val){
$temp = [];
$temp['city'] = $key;
$val_opt = explode('_', $val);
$temp['value'] = $val_opt[0];
$temp['option'] = $val_opt[1];
$res[] = $temp;
}
print_r($res);
Output:
Array
(
[0] => Array
(
[city] => Berlim
[value] => 23
[option] => 5
)
[1] => Array
(
[city] => Rio
[value] => 18
[option] => 3
)
[2] => Array
(
[city] => Tokyo
[value] => 20
[option] => 4
)
)
I have 2 arrays, one with key, another with numeric keys, how can i copy they key, replacing the numeric keys in the exact order?
Array with numeric key
Array
(
[0] => ABCDEFG
[1] => This is my description
[2] => 12.00
[3] => 30.00
[4] => My supplier
[5] => My brand
[6] => Shoes
[7] =>
)
Array 2
Array
(
[productcode] => Product Code
[productitemdesc] => Description
[retailsalesprice] => Selling Price
[currentcost] => Unit Cost
[supplier] => Supplier
[productbrand] => Brand
[productcategory] => Category
[productgroup] => Group
)
I would want something like this
Array
(
[productcode] => ABCDEFG
[productitemdesc] => This is my description
[retailsalesprice] => 12.00
[currentcost] => 30.00
[supplier] => My Supplier
[productbrand] => My Brand
[productcategory] => Shoes
[productgroup] =>
)
Is there any existing functions available for php? Tried array_fill_keys but doesn't seem to be what i want.
You can use the function array_combine() to combine the keys from the second array (for the following example called $array_keys) with the values from the first array (called $array_values):
Example:
$combined = array_combine(array_keys($array_keys), $array_values);
print_r($combined);
This prints out the array exactly like you described.
array_combine way is a lot better but you can use this function as well. This will allow you to modify the values if you want.
function custom_combine($numeric_array, $keyed_array)
{
$temp = array();
$i=0;
foreach($keyed_array as $key=>$val)
{
if(isset($numeric_array[$i]))
$temp[$key] = $numeric_array[$i];
else
$temp[$key] ='';
$i++;
}
return($temp);
}
The other answers are definitely more efficient, but in case you'd like to learn how to manually loop through arrays, something like this should work:
<?php
// The original array
$arr1 = array(
0 => 'ABCDEFG',
1 => 'This is my description',
2 => '12.00',
3 => '30.00',
4 => 'My supplier',
5 => 'My brand',
6 => 'Shoes',
7 => '',
);
// The second array
$arr2 = array(
'productcode' => 'Product Code',
'productitemdesc' => 'Description',
'retailsalesprice' => 'Selling Price',
'currentcost' => 'Unit Cost',
'supplier' => 'Supplier',
'productbrand' => 'Brand',
'productcategory' => 'Category',
'productgroup' => 'Group',
);
// Pre-define the new array to avoid errors
$arr_new = array();
// Manually create a value to increment during our foreach loop
$increment = 0;
// Loop through each value in $arr2
foreach ($arr2 as $key2 => $value2) {
// If the key is set in $arr1, assign the value from $arr1 and the key from $arr2
// to the new array
if (isset($arr1[$increment])) {
$arr_new[$key2] = $arr1[$increment];
}
// Increment the value regardless of whether it was found in $arr1 or not
$increment++;
}
// Remove this if you want... It just displays the values found in $arr_new
print_r($arr_new);
i tested it and work :
<?php
$a=array(
0 => "ABCDEFG",
1 => "This is my description",
2 => "12.00",
3 => '30.00',
4 => 'My supplier',
5 => 'My brand',
6 => 'Shoes',
7 => '',
)
;
$b=array
(
'productcode' => 'Product Code',
'productitemdesc' => 'Description',
'retailsalesprice' => 'Selling Price',
'currentcost' => 'Unit Cost',
'supplier' => 'Supplier',
'productbrand' => 'Brand',
'productcategory' => 'Category',
'productgroup' => 'Group',
);
$j=0;
foreach ($b as $i => $value) {
$b[$i]=$a[$j];
$j++;
}
var_dump($b);
?>
you can use array_combine()
$array3=array_combine($array2,$array1);
print_r($array3);
I have an array with same customerid. I want to merge all same customerid arrays in to one with few amends to the array.
Array
(
[0] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[profession_id] => 8
[profession_name] => Producer
)
[1] => Array
(
[customerid] => 1
[customer_fullname] => John
[profession_id] => 8
[profession_name] => Producer
)
[2] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[profession_id] => 7
[profession_name] => Camera
)
)
So now I want a new array to be created like this:
Array(
[customerid] => 13
[customer_fullname] => Chris
[new_array] => array(
[0]=>[profession_id] => 8, [profession_name] => Producer,
[1]=>[profession_id] => 7, [profession_name] => Camera
)
)
Spent some time on it but wasn't able to get it right
There are better approaches if you're merging lots of records, but if you want a way to just merge two records as stated, I'd just do this:
$array1 = array(
'customerid' => 13
'customer_fullname' => 'John',
'profession_id' => 8,
'profession_name' => 'Producer'
);
$array2 = array(
'customerid' => 13
'customer_fullname' => 'John',
'profession_id' => 7,
'profession_name' => 'Director'
);
function merge_customers($customerA, $customerB)
{
$newCustomer = array();
if ($customerA['customerid'] == $customerB['customerid'])
{
$newCustomer['customerid'] = $customerA['customerid'];
$newCustomer['customer_fullname'] = $customerA['customer_fullname'];
$newCustomer['new_array'] = array(
array(
'profession_id' => $customerA['profession_id'],
'profession_name' => $customerA['profession_name']
),
array(
'profession_id' => $customerB['profession_id'],
'profession_name' => $customerB['profession_name']
)
);
return $newCustomer;
}
/* We can't merge these if they're different customers. */
return NULL;
}
The extended solution which is also well-suited for finding and "merging" multiple groups of entries which has same customerid. Used functions: array_filter, array_count_values, array_keys, array_walk, array_chunk and array_values:
// supposing $arr is your initial array
// finds which 'customerid' has multiple entries
$dupIds = array_filter(array_count_values(array_column($arr, "customerid")), function($v) {
return $v > 1;
});
$dupIds = array_keys($dupIds);
$result = [];
array_walk($arr, function($v) use(&$result, $dupIds) {
if (in_array($v['customerid'], $dupIds)) {
$parts = array_chunk($v, 2, true);
if (!isset($result[$v['customerid']])) {
$result[$v['customerid']] = $parts[0] + ['new_array' => [$parts[1]]];
} else {
$result[$v['customerid']]['new_array'][] = $parts[1];
}
}
});
print_r(array_values($result));
The output:
Array
(
[0] => Array
(
[customerid] => 13
[customer_fullname] => Chris
[new_array] => Array
(
[0] => Array
(
[profession_id] => 8
[profession_name] => Producer
)
[1] => Array
(
[profession_id] => 7
[profession_name] => Camera
)
)
)
)
Quick hack, maybe there is a nicer solution.
Note: The second "for each" loop is only needed if there is the possibility that the arrays don't have the same fields.
function merge($array1, $array2){
$result = array();
foreach($array1 as $key => $value){
if(isset($array2[$key]) && $array2[$key]!=$array1[$key]){
$result[$key][]=$value;
$result[$key][]=$array2[$key];
}else{
$result[$key]=$value;
}
}
foreach($array2 as $key => $value){
if(!isset($result[$key])){
$result[$key] = $value;
}
}
return $result;
}
print_r(merge($array1, $array2));
I have this array in php returned from db
Array
(
[inv_templates] => Array
(
[0] => Array
(
[inven_subgroup_template_id] => 1
[inven_group] => Wires
[inven_subgroup] => CopperWires
[inven_template_id] => 1
[inven_template_name] => CopperWires6G
[constrained] => 0
[value_constraints] =>
[accept_range] => 2 - 16
[information] => Measured Manual
)
[1] => Array
(
[inven_subgroup_template_id] => 1
[inven_group] => Wires
[inven_subgroup] => CopperWires
[inven_template_id] => 2
[inven_template_name] => CopperWires2G
[constrained] => 0
[value_constraints] =>
[accept_range] => 1 - 7
[information] => Measured by Automated Calipers
)
)
)
I need to output this kind of multidimensional stuff
Array
(
[Wires] => Array
(
[inv_group_name] => Wires
[inv_subgroups] => Array
(
[CopperWires] => Array
(
[inv_subgroup_id] => 1
[inv_subgroup_name] => CopperWires
[inv_templates] => Array
(
[CopperWires6G] => Array
(
[inv_name] => CopperWires6G
[inv_id] => 1
)
[CopperWires2G] => Array
(
[inv_name] => CopperWires2G
[inv_id] => 2
)
)
)
)
)
)
I currently do this stuff
foreach ($data['inv_templates'] as $key => $value) {
$processeddata[$value['inven_group']]['inv_group_name'] = $value['inven_group'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_subgroup_id'] = $value['inven_subgroup_template_id'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_subgroup_name'] = $value['inven_subgroup'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_templates'][$value['inven_template_name']]['inv_name'] = $value['inven_template_name'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_templates'][$value['inven_template_name']]['inv_id'] = $value['inven_template_id'];
}
return $processeddata;
EDIT : A var_export
array (
'inv_templates' =>
array (
0 =>
array (
'inven_subgroup_template_id' => '1',
'inven_group' => 'Wires',
'inven_subgroup' => 'CopperWires',
'inven_template_id' => '1',
'inven_template_name' => 'CopperWires6G',
'constrained' => '0',
'value_constraints' => '',
'accept_range' => '2 - 16',
'information' => 'Measured Manual',
),
1 =>
array (
'inven_subgroup_template_id' => '1',
'inven_group' => 'Wires',
'inven_subgroup' => 'CopperWires',
'inven_template_id' => '2',
'inven_template_name' => 'CopperWires6G',
'constrained' => '0',
'value_constraints' => '',
'accept_range' => '1 - 7',
'information' => 'Measured by Automated Calipers',
),
),
)
The foreach is almost unreadable. There must be a simpler way
$processeddata = array();
foreach($data['inv_templates'] as $key => $value) {
$group = $value['inven_group'];
$processeddata[$group]['inv_group_name'] = $group;
$subgroup = &$processeddata[$group]['inv_subgroups'][$value['inven_subgroup']];
$subgroup['inv_subgroup_id'] = $value['inven_subgroup_template_id'];
$subgroup['inv_subgroup_name'] = $value['inven_subgroup'];
$template = $value['inven_template_name'];
$subgroup['inv_templates'][$template]['inv_name'] = $template;
$subgroup['inv_templates'][$template]['inv_id'] = $value['inven_template_id'];
}
return $processeddata;
Untested code. This structures the array in a multidimensional way, and then uses array_merge_recursive to merge them with the already processed data.
if (!isset($processeddata[$value['inven_group']]))
$processeddata[$value['inven_group']] = array();
$processeddata[$value['inven_group']] = array_merge_recursive(
$processeddata[$value['inven_group']],
array(
'inv_group_name' => $value['inven_group'],
'inv_subgroups' => array(
$value['inven_subgroup'] => array(
'inv_subgroup_id' => $value['inven_subgroup_template_id'],
'inv_subgroup_name' => $value['inven_subgroup'],
'inv_templates' => array(
$value['inven_template_name'] => array(
'inv_name' => $value['inven_template_name'],
'inv_id' => $value['inven_template_id'],
),
),
),
),
)
);
I find this format usually works for me. You could do it more efficient, I've just never cared :D
I started traversing at $yourArray['inv_templates'] though.
function groupToStructure(array $rows, array $keys) {
$tree = array();
$keys = array_reverse($keys);
foreach ($rows as $row) {
$subTree = array($row);
foreach ($keys as $key) {
$subTree = array($row[$key] => $subTree);
}
$tree = array_merge_recursive($tree, $subTree);
}
return $tree;
}
print_r(groupToStructure($rows, array('inven_group', 'inven_subgroup', 'inven_template_name')));