I have an array and I need to sort this array in a multilevel array. I'm trying to group it by its fields but I can make it work. Here is the example of the array I have and what I want
Array
(
[0] => Array
(
[id] => sports
[title] => this is sports
)
[1] => Array
(
[id] => cricket
[title] => this is cricket
[under] => sports
)
[2] => Array
(
[id] => batsman
[title] => this is batsman
[under] => cricket
)
[3] => Array
(
[id] => sachin
[title] => this is sachin
[under] => batsman
)
[4] => Array
(
[id] => football
[title] => this is football
[under] => sports
)
[5] => Array
(
[id] => ronaldo
[title] => this is ronaldo
[under] => football
)
)
I need to group this array and make it like this
Array(
[0] => Array(
[id] => Array(
[sports] => Array(
[cricket] => Array(
[batsman] => sachin
)
[football] => fun
)
)
)
)
I tried something like this but it is not working
foreach($my_array as $item) {
//group them by under
$my_grouped_array[$item['under']][] = $item;
}
Any suggestion will be great.
I think this is the most straight-forward way of doing this:
function getChildren($entry,$by_parent){
$children = array();
if (isset($by_parent[$entry['id']])){
foreach ($by_parent[$entry['id']] as $child){
$id = $child['id'];
$children[$id] = getChildren($child,$by_parent);
}
}
return $children;
}
$by_parent = array();
$roots = array();
foreach ($array as $entry){
if (isset($entry['under'])){
$by_parent[$entry['under']][] = $entry;
} else {
$roots[] = $entry;
}
}
$result = array();
foreach ($roots as $entry){
$id = $entry['id'];
$result[$id] = getChildren($entry,$by_parent);
}
$results = array(array('id'=>$results));
NOTE: This isn't quite the format specified in the question, but the question doesn't define how to deal with multiple leaf nodes with the same parent, and this should be easier to traverse anyway, because it's more consistent.
I wrote a recursive function that does what you want, but bare in mind that if you have more than one last element of a branch only the first one will be saved.
Here's the function:
function rearrange(&$result, $my_array, $element = NULL)
{
$found = 0;
$childs = 0;
foreach($my_array as $one) if(#$one['under'] == $element)
{
$found++;
if( ! is_array($result)) $result = array();
$result[$one['id']] = $one['id'];
$childs += rearrange($result[$one['id']], $my_array, $one['id']);
}
if( ! $childs AND is_array($result))
$result = reset($result);
return $found;
}
You can call it like that:
$result = array(array('id' => array()));
rearrange($result[0]['id'], $my_array);
print_r($result);
Use php object:
function populateArray($my_array) {
//Populate the array
while ($my_array as $item) {
$array[$item->id]['id'] = $obj->id;
$array[$item->id]['name'] = $obj->name;
}
return $array;
}
$a = populateArray($array);
echo $a[0]['id'].'<br />';
echo $a[0]['name'].'<br />';
or use new foreach
Related
Here is the raw data
Array
(
[name] => me
[tickets] => Array
(
[1] => Array
(
[equipment] => Array
(
[1] => Array
(
[name] => DVR
[received] => 10
)
[2] => Array
(
[name] => DCT
[received] => 3
)
)
)
[2] => Array
(
[equipment] => Array
(
[1] => Array
(
[name] => DVR
[received] => 4
)
[2] => Array
(
[name] => DCT
[received] => 6
)
)
)
)
)
Users have multiple tickets, but each ticket has the same item with different 'received' amounts. I would like to sum the received amount into one variable/array.
Here is a demo of how I would like to get it to work like
Array
(
[name] => me
[equipment] => Array
(
[DVR] => 14
[DCT] => 9
)
)
Here is my most recent failed attempt at building my own array from a multidimensional array.
foreach($data as $user){
$sum = [];
$sum['name'] = $user->name;
$sum['equipment'] = [];
foreach($user->tickets as $ticket){
foreach($ticket->equipments as $eqpt){
$sum['equipment'][$eqpt['name']] += $eqpt['pivot']['received'];
}
}
print_r($sum);
}
Please try the following code. There's only a single user in your $data, though, so you need to do $data = [$data]; first.
foreach ($data as $user) {
$sum = [];
$sum['name'] = $user['name'];
$sum['equipment'] = [];
foreach($user['tickets'] as $ticket){
foreach($ticket['equipment'] as $eqpt){
$sum['equipment'][$eqpt['name']] += $eqpt['received'];
}
}
print_r($sum);
}
PHP arrays are accessed with square bracket syntax
There's probably a typo in $ticket->equipments.
Try with this:
$array = $data; //$data is your array
$sum = array('name' => $array['name'], 'equipment' => array());
foreach($array['tickets'] as $row) {
for($i = 0; $i < count($row); $i++) {
foreach($row['equipment'] as $infos) {
$sum['equipment'][$infos['name']] += $infos['received'];
//print_r($infos);
}
}
}
print_r($sum);
well, after much googling and trial and error this appears to work
$sum = [];
// $data is a collection returned by Laravel
// I am converting it to an array
foreach($data->toArray() as $user){
$items = [];
foreach($user['tickets'] as $ticket){
foreach($ticket['equipments'] as $eqpt){
$name = $eqpt['name'];
if (! isset($items[$name]))
{
$items[$name] = $eqpt['received'];
} else {
$items[$name] += $eqpt['received'];
}
}
}
$sum[] = [
'name' => $user['name'],
'equipment' => $items
];
}
#tsnorri #Adrian Cid Almaguer
I have a function to convert a .json file to an array:
function jsonToArray($file) {
$json = json_decode(file_get_contents($file), true);
print_r($json); }
This yields an array like this:
Array (
[field1] => value1
[field2] => Array
(
[subfield1] => subvalue1
[subfield2] => subvalue2
[subfield3] => subvalue3
)
)
To interface with existing code, I need these arrays with the fields and values split, like this:
Array (
[0] => Array
(
[0] => field1
[1] => Array
(
[0] => subfield1
[1] => subfield2
[2] => subfield3
)
)
[1] => Array
(
[0] => value1
[1] => Array
(
[0] => subvalue1
[1] => subvalue2
[2] => subvalue3
)
)
)
The code I came up with works if this structure is maintained for all usage but as that can't be guaranteed I need another solution. I'm sure it's something relatively simple, I just can't crack it. Any hints or insight would be much appreciated.
try this code
$arr = array ('field1' => 'value1',
'field2' => array(
'subfield1' => 'subvalue1',
'subfield2' => 'subvalue2',
'subfield3' => 'subvalue3'));
function array_values_recursive($ary) {
$lst = array();
foreach( $ary as $k => $v ) {
if (is_scalar($v)) {
$lst[] = $v;
} elseif (is_array($v)) {
$lst[] = array_values_recursive($v);
}
}
return array_values($lst);
}
function array_keys_recursive($ary) {
$lst = array();
foreach( $ary as $k => $v ) {
if (is_scalar($v)) {
$lst[] = ($k);
} elseif (is_array($v)) {
$lst[] = array_keys_recursive($v);
}
}
return $lst;
}
echo '<pre>';
$arr1 = array();
$arr1[] = array_values_recursive($arr);
$arr1[] = array_keys_recursive($arr);
print_r($arr1);
This might be useful to you: array_values() and array_keys() that and a little of foreach would do the magic.
I have a multi-dimensional array like this:
Array
(
[0] => Array
(
[id] => 1
[email_id] => ok#gmail.com
[password] => test
)
[1] => Array
(
[id] => 2
[email_id] => check#gmail.com
[password] => test
)
[2] => Array
(
[id] => 3
[email_id] => an#gmail.com
[password] => pass
)
)
In the above array, password value is the same in two different rows. I need to merge the arrays which have duplicate values to get the following output:
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[email_id] => ok#gmail.com
[password] => test
)
[1] => Array
(
[id] => 2
[email_id] => check#gmail.com
[password] => test
)
)
[1] => Array
(
[id] => 3
[email_id] => an#gmail.com
[password] => pass
)
)
How to do this? I've tried array_merge() & foreach() loops, but I can't get this output.
Try,
$arr = array( array('id'=>1, 'email_id'=>'ok#gmail.com', 'password'=>'test'),
array('id'=>2, 'email_id'=>'check#gmail.com', 'password'=>'test'),
array('id'=>3, 'email_id'=>'an#gmail.com', 'password'=>'pass'));
$new_arr = array();
foreach($arr as $k => $v) {
if( is_array($arr[$k+1]) && $arr[$k]['password'] === $arr[$k + 1]['password'] )
$new_arr[] = array($arr[$k], $arr[$k+1]);
else if( in_array_recursive($arr[$k]['password'], $new_arr) === FALSE )
$new_arr[] = $v;
}
function in_array_recursive( $val, $arr) {
foreach( $arr as $v ) {
foreach($v as $m) {
if( in_array($val, $m ) )
return TRUE;
}
}
return FALSE;
}
print_r($new_arr);
Demo
You only want to create more depth in your output array if there is more than one entry in the group. I personally wouldn't want that kind of variability in a data structure because the code that will print the data will need to go to extra trouble to handle associative rows of data that might be on different levels.
Anyhow, here's how I would do it with one loop...
Foreach Loop Code: (Demo)
$result = [];
foreach ($array as $row) {
if (!isset($result[$row['password']])) {
$result[$row['password']] = $row; // save shallow
} else {
if (isset($result[$row['password']]['id'])) { // if not deep
$result[$row['password']] = [$result[$row['password']]]; // make original deeper
}
$result[$row['password']][] = $row; // save deep
}
}
var_export(array_values($result)); // print without temporary keys
Functional Code: (Demo)
var_export(
array_values(
array_reduce(
$array,
function($result, $row) {
if (!isset($result[$row['password']])) {
$result[$row['password']] = $row;
} else {
if (isset($result[$row['password']]['id'])) {
$result[$row['password']] = [$result[$row['password']]];
}
$result[$row['password']][] = $row;
}
return $result;
},
[]
)
)
);
foreach ($this->CsInventory as $value)
{
print_r($value) // print 1
$vname = $value[] = $value['VesselName'];
$total = $value[] = $value['Total'];
$Box = $value[] = $value['Box'];
print_r($value); // print 2
$rdata .= '<td>'.$vname.'</td>
<td>'.$total.'</td>
<td>'.$Box.'</td>';
}
Print 1
Array
(
[VesselName] => MARIANNE
[Total] => 13838
[Box] => 1156
)
Array
(
[Box] => 154
)
Array
(
[Box] => 3825
)
Array
(
[Box] => 50571
)
print 2
Array
(
[VesselName] => MARIANNE
[Total] => 15452
[Box] => 1156
[0] => MARIANNE
[1] => 15452
[2] => 1156
)
Array
(
[Box] => 2276
[0] =>
[1] =>
[2] => 2276
)
Array
(
[Box] => 3825
[0] =>
[1] =>
[2] => 3825
)
Array
(
[Box] => 49235
[0] =>
[1] =>
[2] => 49235
)
i how can i remove an empty value in the array? i try many ways but i can get any solution.. so decide to here in the forum?
I'd try to reduce effort.
foreach ($this->CsInventory as $value)
{
foreach ($value as $key => $item)
{
$value[] = $item;
$rdata .= "<td>$item</td>";
}
print_r($value)
}
As a general comment, not sure why you're adding anonomous values back to the $values stack, might be better to use a different array.
If you have specific array elements you want to get rid of, you can use unset($array[$key]);
You could also prevent them getting into the array in the first place by using
if($value['VesselName']) {$vname = $value[] = $value['VesselName'];}
instead of simply
$vname = $value[] = $value['VesselName'];
function array_remove_empty($arr){
$narr = array();
while(list($key, $val) = each($arr)){
if (is_array($val)){
$val = array_remove_empty($val);
// does the result array contain anything?
if (count($val)!=0){
// yes :-)
$narr[$key] = $val;
}
}
else {
if (trim($val) != ""){
$narr[$key] = $val;
}
}
}
unset($arr);
return $narr;
}
array_remove_empty(array(1,2,3, '', array(), 4)) => returns array(1,2,3,4)
I want a function that
searches through my array, and
returns all the
children to a specific node. What is
the most appropriate way to do this?
Will recursion be necessary in this case?
I have previously constructed a few quite complex functions that iterates with or without the help of recursion through multi-dimensional arrays and re-arranging them, but this problem makes me completely stuck and I can't just get my head around it...
Here's my array:
Array
(
[1] => Array (
[id] => 1
[parent] => 0
)
[2] => Array (
[id] => 2
[parent] => 1
)
[3] => Array (
[id] => 3
[parent] => 2
)
)
UPDATE:
The output which I want to get. Sorry for the bad example, but I'll blame it on lack of knowledge on how to format the stuff I need to do :)
function getAllChildren($id) {
// Psuedocode
return $array;
}
getAllChildren(1); // Outputs the following:
Array
(
[2] => Array (
[id] => 2
[parent] => 1
)
[3] => Array (
[id] => 3
[parent] => 2
)
)
$nodes = array( 1 => array ( 'id' => 1,
'parent' => 0
),
2 => array ( 'id' => 2,
'parent' => 1
),
3 => array ( 'id' => 3,
'parent' => 2
)
);
function searchItem($needle,$haystack) {
$nodes = array();
foreach ($haystack as $key => $item) {
if ($item['parent'] == $needle) {
$nodes[$key] = $item;
$nodes = $nodes + searchItem($item['id'],$haystack);
}
}
return $nodes;
}
$result = searchItem('1',$nodes);
echo '<pre>';
var_dump($result);
echo '</pre>';
Non-recursive version of the searchItem() function:
function searchItem($needle,$haystack) {
$nodes = array();
foreach ($haystack as $key => $item) {
if (($item['parent'] == $needle) || array_key_exists($item['parent'],$nodes)) {
$nodes[$key] = $item;
}
}
return $nodes;
}
(assumes ordering of the parents/children, so a child node isn't included in the array unless the parent is already there)
<?php
function searchItem($needle)
{
foreach ($data as $key => $item)
{
if ($item['id'] == $needle)
{
return $key;
}
}
return null;
}
?>
Check out the array_walk_recursive() function in PHP:
http://www.php.net/manual/en/function.array-walk-recursive.php