Group Array by category - php

I am facing problem In grouping array with the Key:-
I have an php array Which has following elecment in it.
$array = array(
'0' => array ( 'id' => 'food,Travel', 'names' => 'chimpanzee' ),
'1' => array ( 'id' => 'food', 'name' => 'meeting' ),
'2' => array ( 'id' => 'Z1', 'name' => 'dynasty' ),
'3' => array ( 'id' => 'X', 'name' => 'chocolate' ),
'4' => array ( 'id' => 'Travel', 'name' => 'bananas' ),
'5' => array ( 'id' => 'Travel', 'name' => 'fantasy' ),
'6' => array ( 'id' => 'Travel', 'name' => 'football' )
);
When I try with following code:-
$newarray= array();
foreach($array as $key => $value){
$newarray[$value['id']][$key] = $value;
}
I am getting below result Array Here food,travel is created another array but I want to please those to respective category "Food goes to food" and travel goes to travel"
(
[food,Travel] => Array
(
[0] => Array
(
[id] => food,Travel
[names] => chimpanzee
)
)
[food] => Array
(
[1] => Array
[id] => food,Travel
[names] => chimpanzee
)
(
[id] => food
[name] => meeting
)
)
[Z1] => Array
(
[2] => Array
(
[id] => Z1
[name] => dynasty
)
)
[X] => Array
(
[3] => Array
(
[id] => X
[name] => chocolate
)
)
[Travel] => Array
(
[4] => Array
(
[id] => Travel
[name] => bananas
)
[5] => Array
(
[id] => Travel
[name] => fantasy
)
[6] => Array
(
[id] => Travel
[name] => football
)
)
)
But I am want following result:- Food should Go to food category and travels should go to travels category like:-
Array
(
[food] => Array
(
// Food should come at food category
[0] => Array
(
[id] => food
[names] => chimpanzee
)
)
(
[1] => Array
(
[id] => food
[name] => meeting
)
)
[Z1] => Array
(
[2] => Array
(
[id] => Z1
[name] => dynasty
)
)
[X] => Array
(
[3] => Array
(
[id] => X
[name] => chocolate
)
)
[Travel] => Array
(
( // Travel should come at travel category
[0] => Array
(
[id] => food
[names] => chimpanzee
)
)
[4] => Array
(
[id] => Travel
[name] => bananas
)
[5] => Array
(
[id] => Travel
[name] => fantasy
)
[6] => Array
(
[id] => Travel
[name] => football
)
)
)

When id has ,, just explode it, check the demo
$result = [];
foreach($array as $k => $v){
if(strpos($v["id"],",")) {
$ids = explode(",", $v["id"]);
foreach ($ids as $id) {
$result[$id][$k] = $v;
}
}else{
$result[$v["id"]][$k] = $v;
}
}
var_dump($result);

No need to make it complex, like some have suggested, use explode()
https://3v4l.org/jVK6j
$newarray= [];
foreach($array as $key => $value) {
if(is_array(explode(",", $value["id"]))) {
foreach(explode(",", $value["id"]) as $category) {
$newarray[$category][$key] = $value;
$newarray[$category][$key]["id"] = $category;
}
} else {
$newarray[$value["id"]][$key] = $value;
}
}
var_dump($newarray);
You could even remove $key since these will be auto incremented.
foreach($array as $value) {
if(is_array(explode(",", $value["id"]))) {
foreach(explode(",", $value["id"]) as $category) {
$value["id"] = $category;
$newarray[$category][] = $value;
}
} else {
$newarray[$value["id"]][] = $value;
}
}

Related

How to build tree structure from array in PHP

I have following table:
$arr = array(
array('id'=>100, 'year'=>2019, 'month'=>9, 'name'=>'a'),
array('id'=>101, 'year'=>2019, 'month'=>12, 'name'=>'b'),
array('id'=>102, 'year'=>2020, 'month'=>1, 'name'=>'c'),
array('id'=>103, 'year'=>2020, 'month'=>2, 'name'=>'d'),
);
With the code below
$tree = array();
foreach ($arr as $row) {
$tree[$row['year']] = array(
$row['month'] => array (
'id' => $row['id'],
'name' => $row['name'],
),
);
}
I would like to get following result - this structure as a tree:
Array
(
[2019] => Array
(
[9] => Array
(
[id] => 100
[name] => a
)
[12] => Array
(
[id] => 101
[name] => b
)
)
[2020] => Array
(
[1] => Array
(
[id] => 102
[name] => c
)
[2] => Array
(
[id] => 103
[name] => d
)
)
)
Unfortunately I get only following one with single "branches":
Array
(
[2019] => Array
(
[12] => Array
(
[id] => 101
[name] => b
)
)
[2020] => Array
(
[2] => Array
(
[id] => 103
[name] => d
)
)
)
What is missing here? why previous rows disappear from the structure?
As you want the year and month as the main indexes, you need to use both of these when adding the data into the $tree...
$tree = array();
foreach ($arr as $row) {
$tree[$row['year']][$row['month']] = [ 'id' => $row['id'],
'name' => $row['name']];
}
with your test data, this gives...
Array
(
[2019] => Array
(
[9] => Array
(
[id] => 100
[name] => a
)
[12] => Array
(
[id] => 101
[name] => b
)
)
[2020] => Array
(
[1] => Array
(
[id] => 102
[name] => c
)
[2] => Array
(
[id] => 103
[name] => d
)
)
)
You have mistake in key's names - bl_year, bl_month not exist:
foreach ($arr as $row) {
$tree[$row['year']] = array(
$row['month'] => array (
'id' => $row['id'],
'name' => $row['name'],
),
);
}

PHP array with n level deep

Assuming I have an array and recursively want to do some task. I have spent one day for this unable to solve this. May be my logic is not good.
Any help on how to do such thing in an efficient way would save my days.
I have an array with n level deep, looking like:
Array
(
[0] => Array
(
[name] => user1
[email] => user1#demo.com
[depth] => 1
)
[1] => Array
(
[name] => user2
[email] => user2#demo.com
[depth] => 1
[0] => Array
(
[0] => Array
(
[name] => user2.1
[email] => user2.1#demo.com
[depth] => 2
)
)
)
[2] => Array
(
[name] => user3
[email] => user3#demo.com
[depth] => 1
[0] => Array
(
[0] => Array
(
[name] => user3.1
[email] => user3.1#demo.com
[depth] => 2
[0] => Array
(
[0] => Array
(
[name] => user3.1.1
[email] => user3.1.1#demo.com
[depth] => 3
)
)
)
[1] => Array
(
[name] => user3.2
[email] => user3.2#demo.com
[depth] => 2
)
)
)
)
I want to change above array in exactly this format:
array(
0 => array(
'name' => 'user1',
),
1 => array(
'name' => 'user2',
'children' => array(
0 => array(
'name' => 'user2.1',
) ,
) ,
) ,
2 => array(
'name' => 'user3',
'children' => array(
0 => array(
'name' => 'user3.1',
'children' => array(
0 => array(
'name' => 'user3.1.1',
) ,
) ,
) ,
1 => array(
'name' => '3.2',
)
) ,
) ,
)
Edited:
I am using this code and working fine if i want to show data in tree format but unable to push data into array as i want.
function displayArrayRecursively($arr, $indent='') {
if ($arr) {
foreach ($arr as $key => $value) {
if (is_array($value)) {
displayArrayRecursively($value, $indent . '-->');
} else {
if ($key == 'name')
{
echo "$indent $value <br>";
}
else {
continue;
}
}
}
}
}
displayArrayRecursively($userListArray);
Can anyone suggest me how to do this?
Thank you
This function will do what you want:
function process_nodes($nodes) {
$new = array();
foreach ($nodes as $node) {
$new[] = array('name' => $node['name']);
if (isset($node[0])) {
$new[count($new)-1]['children'] = process_nodes($node[0]);
}
}
return $new;
}
print_r(process_nodes($data));
Output:
Array
(
[0] => Array
(
[name] => user1
)
[1] => Array
(
[name] => user2
[children] => Array
(
[0] => Array
(
[name] => user2.1
)
)
)
[2] => Array
(
[name] => user3
[children] => Array
(
[0] => Array
(
[name] => user3.1
[children] => Array
(
[0] => Array
(
[name] => user3.1.1
)
)
)
[1] => Array
(
[name] => user3.2
)
)
)
)

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',
)

fill an array with missing values and keys

I have this array $all_zones that comes sometimes with missing keys and values and I would like to fill the array with empty values for the messing keys, here's the array:
Array
(
[0] => Array
(
[id_zone] => 1
[name] => Europe
[price] => Array
(
[0] => 3.00
[1] => 6.00
)
[id_delivery] => Array
(
[0] => 1
[1] => 2
)
)
[1] => Array
(
[id_zone] => 3
[name] => Asia
)
[2] => Array
(
[id_zone] => 4
[name] => Africa
[price] => Array
(
[0] => 3.00
[1] => 6.00
)
[id_delivery] => Array
(
[0] => 3
[1] => 4
)
)
[3] => Array
(
[id_zone] => 5
[name] => Oceania
)
)
The thing is the $all_zones[$key]['price'] depend on how many ranges there's for each Zone, inthis case $range_count = count($all_ranges); will display 2, so I'd like to fill the missing keys for 2 times : Here's the output:
Array
(
[0] => Array
(
[id_zone] => 1
[name] => Europe
[price] => Array
(
[0] => 3.00
[1] => 6.00
)
[id_delivery] => Array
(
[0] => 1
[1] => 2
)
)
[1] => Array
(
[id_zone] => 3
[name] => Asia
[price] => Array
(
[0] =>
[1] =>
)
[id_delivery] => Array
(
[0] =>
[1] =>
)
)
[2] => Array
(
[id_zone] => 4
[name] => Africa
[price] => Array
(
[0] => 3.00
[1] => 6.00
)
[id_delivery] => Array
(
[0] => 3
[1] => 4
)
)
[3] => Array
(
[id_zone] => 5
[name] => Oceania
[price] => Array
(
[0] =>
[1] =>
)
[id_delivery] => Array
(
[0] =>
[1] =>
)
)
)
Here's what I've tried so far and didn't succeed:
$range_count = count($all_ranges);
$i=0;
foreach ($all_zones as $key => $value) {
if(isset($value['id_zone']) && isset($value['name']) && (!isset($value['price']) || !isset($value['id_delivery']))){
if($range_count>$i){
$disabled[]=$key;
$all_zones[$key]['price'][] = '';
$all_zones[$key]['id_delivery'][] = '';
}
$i++;
}
}
Any help with this? Much appreciated.
try this
$range_count = count($all_ranges);
foreach ($all_zones as $key => $value) {
if(isset($value['id_zone']) && isset($value['name']) && (!isset($value['price']) || !isset($value['id_delivery']))){
$disabled[]=$key;
if((!isset($value['price']))
{
for($i=0; $i<$range_count<$i++)
{
$all_zones[$key]['id_delivery'][] = '';
}
}
if((!isset($value['id_delivery']))
{
for($i=0; $i<$range_count<$i++)
{
$all_zones[$key]['id_delivery'][] = '';
}
}
}
}
You might have operator precedence problem.
( (!isset($value['price']) || !isset($value['id_delivery'])) )
The way to do this is to loop through the array, with an array_merge() on each array within the parent array to set your 'defaults'.
$zone_template = array(
'id_zone' => '',
'name' => '',
'price' => array(
0 => '',
1 => ''
),
'id_delivery' = array(
0 => '',
1 => ''
)
);
foreach ($all_zones as $zone) {
array_merge($zone_template, $zone);
}
Can also be done with array_walk()

Move array with same value inside the same array

This is my array.
Array
(
[id] => 1
[color] => "White"
[something] => Array
(
[country] => "France"
[city] => "Paris"
)
)
Array
(
[id] => 2
[color] => "Black"
[something] => Array
(
[country] => "Germany"
[city] => "Berlin"
)
)
Array
(
[id] => 2
[color] => "Red"
[something] => Array
(
[country] => "Russia"
[city] => "Moscow"
)
)
I want to group arrays with same id value. This should be the output:
[0] => Array
(
[0] => Array
(
[id] => 1
[color] => "White"
[something] => Array
(
[country] => "France"
[city] => "Paris"
)
)
)
[1] => Array
(
[0] => Array
(
[id] => 2
[color] => "Black"
[something] => Array
(
[country] => "Germany"
[city] => "Berlin"
)
)
[1] => Array
(
[id] => 2
[color] => "Red"
[something] => Array
(
[country] => "Russia"
[city] => "Moscow"
)
)
)
I tried with tens of foreach statements but there's no way for me to get arrays with same id inside the same array. Is it probably related with the fact that it's a multidimensional array? Should I use 2 nested foreach to get the result?
Code:
<?php
$arr = array(
array(
'id' => 1,
'color' => 'white',
'something' => array(
'country' => 'France',
'city' => 'Paris',
),
),
array(
'id' => 2,
'color' => 'Black',
'something' => array(
'country' => 'Germany',
'city' => 'Berlin',
),
),
array(
'id' => 2,
'color' => 'Red',
'something' => array(
'country' => 'Russia',
'city' => 'Moscow',
),
),
);
function groupify($arr) {
$new = array();
foreach ($arr as $item) {
if (!isset($new[$item['id']])) {
$new[$item['id']] = array();
}
$new[$item['id']][] = $item;
}
return $new;
}
print_r(groupify($arr));
Result:
Array
(
[1] => Array
(
[0] => Array
(
[id] => 1
[color] => white
[something] => Array
(
[country] => France
[city] => Paris
)
)
)
[2] => Array
(
[0] => Array
(
[id] => 2
[color] => Black
[something] => Array
(
[country] => Germany
[city] => Berlin
)
)
[1] => Array
(
[id] => 2
[color] => Red
[something] => Array
(
[country] => Russia
[city] => Moscow
)
)
)
)
if you don't want to preserve keys, just call array_values before return.
Use id for key of new array.
$a[$array[id]][] = $array;
If you wanted to use a foreach:
<?php
$return = array();
foreach($array as $key => $innerArray) {
$return[$innerArray['id']][]= $innerArray;
}
Now $return contains them groped by ID, where keys 1 and 2 are your IDs
array(
1 => array(
array(/** **/)
),
2 => array(
array(/** **/),
array(/** **/)
);
);
You can then access your groups like this:
foreach($return as $key => $groupArray) {
// you have the groups here
foreach($groupArray as $id => $singleArray) {
// singleArray contains your id, colour etc
}
}
foreach($return[1] as $groupOne) {
// all arrays with id = 1
}

Categories