PHP grouping array - php

i've got the following array:
$comments = array();
$comments[] = array('member_id' => '17',
'time' => '2011-05-10 11:10:00',
'name' => 'John Smith',
'comment' => 'Test Comment 1');
$comments[] = array('member_id' => '25',
'time' => '2011-05-10 11:26:00',
'name' => 'David Jones',
'comment' => 'Test Comment 2');
$comments[] = array('member_id' => '17',
'time' => '2011-05-10 13:15:00',
'name' => 'John Smith',
'comment' => 'Test Comment 3');
How would i go about grouping it by member_id? So I'll be able to display the comments on the page with the following formatting:
John Smith(2 comments)
2011-05-10 11:10:00 | Test Comment 1
2011-05-10 13:15:00 | Test Comment 3
David Jones(1 comment)
2011-05-10 11:26:00 | Test Comment 2

One solution is to sort them by the name field (check out usort for that), but even easier might be to just populate a new array in this way:
$grouped = array();
foreach($comments as $c) {
if(!isset($grouped[$c['name']]) {
$grouped[$c['name']] = array();
}
$grouped[$c['name']][] = $c;
}
//Now it's just a matter of a double foreach to print them out:
foreach($grouped as $name => $group) {
//print header here
echo $name, "<br>\n";
foreach($group as $c) {
//print each comment here
}
}

I would suggest using a second grouping array
$groups[] = array();
foreach( $comment as $k=>$v ) {
$groups[$v['member_id']][] = $k
}
And then to print it
foreach( $group as $m_id=>$arr ) {
echo "Group $m_id<br/>\n";
foreach( $arr as $k ) {
echo $comment[$k]."<br/>\n";
}
}

You should try with taking multi-dimensional array.
$comment_groups[] = array();
$m_id = '';
foreach( $comment_groups as $key=>$val ) {
if($key == 'member_id'){
$m_id = $val;
}
$comment_groups[$m_id]][] = $val;
}
Then you can print as you want to display.

Related

php dynamic table from muldimentional array

can you give me idea how to implement this idea for "dynamic" html table.
I have an array
$arr = array(
array(
'label' => 'First name',
'data' => array(
array('fname' => 'John'),
array('fname' => 'Ralph'),
),
),
array(
'label' => 'Last name',
'data' => array(
array('lname' => 'Doe'),
array('lname' => 'Loren'),
),
),
array(
'label' => 'Description',
'data' => array(
array('description' => 'Something bout John'),
array('description' => 'Something about Ralph'),
),
),
);
Now from the keys 'label' im creating the table columns
---------------------------------------
|First Name | Last Name | Description |
---------------------------------------
The problem is how to put 'fname' keys in the first column, 'lname' in the second and 'description' in the third.
With this part of code im trying to put the data in all columns
private function tableBody()
{
$data = $this->data;
$table = '<tbody>';
foreach($data as $key => $value){
foreach($value['data'] as $k => $v){
$table .= '<tr>';
foreach($v as $col => $name){
$table .= '<td>' . $name . '</td>';
}
$table .= '</tr>';
}
}
$table .= '</tbody>';
return $table;
}
Also my idea is not to hard code array keys for multiple usage(except label and data).
First I would remap the data to process it in loops.
$labels = [];
$rows = [];
foreach($arr as $column) {
$label = $column['label'];
$labels[] = $label;
foreach($column['data'] as $key => $value) {
$rows[$label][] = $value;
}
}
Now print out the labels with the headline.
echo "<table>\n";
echo "<tr>";
foreach($labels as $label) echo "<th>{$label}</th>";
echo "</tr>\n";
Iterate through the rows and create the HTML.
$labelCount = count($labels);
$rowCount = count($rows[$labels[0]]);
while($rowCount) {
echo "<tr>";
for ($i = 0; $i < $labelCount; $i++) {
$current = array_shift($rows[$labels[$i]]);
$value = reset($current);
echo "<td>{$value}</td>";
}
echo "</tr>\n";
$rowCount--;
}
echo "</table>\n";
This gives a table like below
<table>
<tr><th>First name</th><th>Last name</th><th>Description</th></tr>
<tr><td>John</td><td>Doe</td><td>Something bout John</td></tr>
<tr><td>Ralph</td><td>Loren</td><td>Something about Ralph</td></tr>
</table>
You need to manipulate the initial array to reduce it to something more manageable. You could brute force your way like so:
function reduce($data) {
$ret = [];
foreach ($data as $d1) {
// column header could have been fetched here
foreach ($d1 as $k2 => $d2) {
// keeping track of what label we need
$key = '';
// keeping the values together
$child = [];
// discarding non arrays
if (is_array($d2)) {
foreach ($d2 as $d3) {
// identifier fetch from this level
foreach ($d3 as $k4 => $d4) {
$key = $k4;
$child[] = $d4;
}
}
}
// assigning back to the main array only if we have something
if (!empty($child)) {
$ret[$key] = $child;
}
}
}
return $ret;
}
That will return the following:
Array
(
[fname] => Array
(
[0] => John
[1] => Ralph
)
[lname] => Array
(
[0] => Doe
[1] => Loren
)
[description] => Array
(
[0] => Something bout John
[1] => Something about Ralph
)
)

php - compare multi arrays and output in order

I have two arrays:
Array 1:
$art_style = ['Title1','Title2','Title3'];
Array 2:
array(
'name' => array('Title1', 'Title3', 'Title2'),
'value' => array('2,0x1,0', '2,5', '15,0'
);
I need to compare Array 2 "name" with Array 1 and output the values from Array 2 in the order of Array 1.
So the output in this case would be:
2,0x1,0 - 15,0 - 2,5
Any Idea how I could achieve that?
Try something like this:
// Array1 order
foreach ($art_style as $key => $value) {
if(in_array($value,$array2['name']))
echo $array2['value'][$key];
}
// Array2 order
foreach ($array2['name'] as $key => $value) {
if(in_array($value,$art_style))
echo $array2['value'][$key];
}
Little Long Method. But, It Worked.
<?
$array1 = ['Title1','Title2','Title3'];
$array2=array(
'name' => array('Title1', 'Title3', 'Title2'),
'value' => array('2,0x1,0', '2,5', '15,0')
);
$SizeofArray2=sizeof($array2['name']);
for($i=0;$i<$SizeofArray2;$i++)
{
$Array2Value= $array2['name'][$i];
for($j=0;$j<sizeof($array1);$j++)
{
if($Array2Value==$array1[$j])
{
if($j==$i)
{
echo " ".$array2['value'][$i];
}
if($j!=$i)
{
echo " -".$array2['value'][$i];
}
}
}
}
?>
Output: 2,0x1,0 -2,5 -15,0
try this:
$art_style = array('Title1','Title2','Title3');
$array2 = array(
'name' => array('Title1', 'Title3', 'Title2'),
'value' => array('2,0x1,0', '2,5', '15,0')
);
foreach ($art_style as $style) {
foreach ($array2['name'] as $id => $name) {
if ($name == $style) {
echo $array2['value'][$id].' - ';
break;
}
}
}

PHP: create array from arrays

I have a form that is posting 4 arrays that I need to combine and eventually compose to email. The four arrays:
$quantityArray = $this->input->post('qty');
$dimensionArray = $this->input->post('dimension');
$thicknessArray = $this->input->post('thickness');
$descriptionArray = $this->input->post('description');
will all have the same array length and each index will be related. How do I combine the 4 arrays such as
[0]
'qty' => '1',
'dimenesion => '2x2',
'thickness' => '2in',
'description' => 'this is the description'
[1]
'qty' => '1',
'dimenesion => '2x2',
'thickness' => '2in',
'description' => 'this is the description'
I have tried array_combined, array_merged and can't get the results that I am looking for. Thanks for the help on this.
If you have same length for those arrays here is example code:
$resultArray = array();
foreach($quantityArray as $index => $qty) {
$resultArray[$index]['qty'] = $qty;
$resultArray[$index]['dimenesion'] = $dimensionArray[$index];
$resultArray[$index]['thickness'] = $thicknessArray[$index];
$resultArray[$index]['description'] = $descriptionArray [$index];
}
print_r($resultArray);
This also may work:
<?php
//...
$quantityArray = $this->input->post('qty');
$dimensionArray = $this->input->post('dimension');
$thicknessArray = $this->input->post('thickness');
$descriptionArray = $this->input->post('description');
//
// combine them:
//
$combined = array();
$n = count($quantityArray);
for($i = 0; $i < $n; $i++)
{
$combined[] = array(
'qty' => $quantityArray[$i],
'dimenesion' => $dimensionArray[$i],
'thickness' => $thicknessArray[$i],
'description' => $descriptionArray[$i]
);
}
//
echo "<pre>";
print_r($combined);
echo "</pre>";
?>
If we assume that we have same length for those arrays here is my codes:
$quantityArray = array(1, 1, 5, 3);
$dimensionArray = array("2x2", "3x3", "4x4", "2x2");
$thicknessArray = array("2in", "3in", "4in", "2in");
$descriptionArray = array("this is the description 1", "this is the description 2 ", "this is the description3 ", "this is the description4" );
$myCombinArray = array();
foreach ( $quantityArray as $idx => $val ) {
$subArray = array (
'qty' => $quantityArray [$idx],
'dimenesion' => $dimensionArray [$idx],
'thickness' => $thicknessArray [$idx],
'description' => $descriptionArray [$idx]
);
array_push ( $myCombinArray, $subArray );
}
print_r($myCombinArray);
How about an easy way if there are always those 4 arrays:
$quantityArray = $this->input->post('qty');
$dimensionArray = $this->input->post('dimension');
$thicknessArray = $this->input->post('thickness');
$descriptionArray = $this->input->post('description');
$combinedArray = [$quantityArray, $dimensionArray, $thicknessArray, $descriptionArray];
# old syntax:
# $combinedArray = array($quantityArray, $dimensionArray, $thicknessArray, $descriptionArray);

Combine repeating elements as array in a multidimensional array

I was wondering when working with multimedional arrays, if a certain key is the same, is there a way to combine the contents of other keys into its own array if a certain key is the same?
Something like this:
// name is the same in both arrays
array(
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '1234567'
),
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '5556734'
)
)
into something like this
array(
array(
'name' => 'Pepsi',
'store' => array('Over here', 'Over here'),
'number' => array('1234567', '5556734')
)
)
The defining key is checking if the name element is the same for the other arrays.
You can try a function like this.
function mergeByKey($array,$key){
$tmp_array = array();
foreach ( $array as $k => $row ) {
$merged = false;
foreach ($tmp_array as $k2 => $tmp_row){
if ($row[$key] == $tmp_row[$key]){
foreach ( $row as $k3 => $value ) {
if ($k3 == $key) continue;
$tmp_array[$k2][$k3][] = $value;
$merged = true;
}
}
if ($merged) break;
}
if (!$merged) {
$new_row = array();
foreach ( $row as $k4 => $value ) {
if ($k4 == $key) $new_row[$k4] = $value;
else $new_row[$k4] = array($value);
}
$tmp_array[] = $new_row;
}
}
foreach ( $tmp_array as $t => $row ) {
foreach ( $row as $t2 => $value ) {
if ( count($value) == 1 && $t2 != $key ) $tmp_array[$t][$t2] = $value[0];
}
}
return $tmp_array;
}
passing the array as first parameter and the key as second one.
I'm referencing to your array structure
edited: missed a piece
edited2: if resultin array contains elements with one string, it returns a string and not a array with one element
demo
This function uses a given field name as the grouping identifier and turns all other fields into arrays.
Note that single occurrences of your field name will yield arrays with a single element for the other fields. I wasn't sure whether that's a desirable trait, but just making sure you know ;-)
$arr = array(
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '1234567'
),
array(
'name' => 'Pepsi',
'store' => 'Over here',
'number' => '5556734'
)
);
function mergeArray($array, $column)
{
$res = array();
foreach ($array as $item) {
foreach ($item as $key => $value) {
if ($key === $column) {
$res[$column][$key] = $value;
} else {
$res[$column][$key][] = $value;
}
}
}
return array_values($res);
}
print_r(mergeArray($arr, 'name'));
Demo
Thanks to Gianni Lovece for her answer but I was able to develop a much simpler solution based on this problem. Just plug in the $result_arr to browse through and the $key you want to use as basis and it immediately outputs a multidimensional array with non-repeating values for repeating elements (see example below).
function multiarray_merge($result_arr, $key){
foreach($result_arr as $val){
$item = $val[$key];
foreach($val as $k=>$v){
$arr[$item][$k][] = $v;
}
}
// Combine unique entries into a single array
// and non-unique entries into a single element
foreach($arr as $key=>$val){
foreach($val as $k=>$v){
$field = array_unique($v);
if(count($field) == 1){
$field = array_values($field);
$field = $field[0];
$arr[$key][$k] = $field;
} else {
$arr[$key][$k] = $field;
}
}
}
return $arr;
}
For example, in the sample array for this question, running multiarray_merge($mysample, 'name') returns
array(
'Pepsi' => array(
'name' => 'Pepsi',
'store' => 'Over here', // String: Not an array since values are not unique
'number' => array('1234567', '5556734') // Array: Saved as array since values are unique
)
);

Get array's key recursively and create underscore separated string

Right now i got an array which has some sort of information and i need to create a table from it. e.g.
Student{
[Address]{
[StreetAddress] =>"Some Street"
[StreetName] => "Some Name"
}
[Marks1] => 100
[Marks2] => 50
}
Now I want to create database table like which contain the fields name as :
Student_Address_StreetAddress
Student_Address_StreetName
Student_Marks1
Student_Marks2
It should be recursive so from any depth of array it can create the string in my format.
You can use the RecursiveArrayIterator and the RecursiveIteratorIterator (to iterate over the array recursively) from the Standard PHP Library (SPL) to make this job relatively painless.
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
$keys = array();
foreach ($iterator as $key => $value) {
// Build long key name based on parent keys
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$key = $iterator->getSubIterator($i)->key() . '_' . $key;
}
$keys[] = $key;
}
var_export($keys);
The above example outputs something like:
array (
0 => 'Student_Address_StreetAddress',
1 => 'Student_Address_StreetName',
2 => 'Student_Marks1',
3 => 'Student_Marks2',
)
(Working on it, here is the array to save the trouble):
$arr = array
(
'Student' => array
(
'Address' => array
(
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => '100',
'Marks2' => '50',
),
);
Here it is, using a modified version of #polygenelubricants code:
function dfs($array, $parent = null)
{
static $result = array();
if (is_array($array) * count($array) > 0)
{
foreach ($array as $key => $value)
{
dfs($value, $parent . '_' . $key);
}
}
else
{
$result[] = ltrim($parent, '_');
}
return $result;
}
echo '<pre>';
print_r(dfs($arr));
echo '</pre>';
Outputs:
Array
(
[0] => Student_Address_StreetAddress
[1] => Student_Address_StreetName
[2] => Student_Marks1
[3] => Student_Marks2
)
Something like this maybe?
$schema = array(
'Student' => array(
'Address' => array(
'StreetAddresss' => "Some Street",
'StreetName' => "Some Name",
),
'Marks1' => 100,
'Marks2' => 50,
),
);
$result = array();
function walk($value, $key, $memo = "") {
global $result;
if(is_array($value)) {
$memo .= $key . '_';
array_walk($value, 'walk', $memo);
} else {
$result[] = $memo . $key;
}
}
array_walk($schema, 'walk');
var_dump($result);
I know globals are bad, but can't think of anything better now.
Something like this works:
<?php
$arr = array (
'Student' => array (
'Address' => array (
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => array(),
'Marks2' => '50',
),
);
$result = array();
function dfs($data, $prefix = "") {
global $result;
if (is_array($data) && !empty($data)) {
foreach ($data as $key => $value) {
dfs($value, "{$prefix}_{$key}");
}
} else {
$result[substr($prefix, 1)] = $data;
}
}
dfs($arr);
var_dump($result);
?>
This prints:
array(4) {
["Student_Address_StreetAddress"] => string(11) "Some Street"
["Student_Address_StreetName"] => string(9) "Some Name"
["Student_Marks1"] => array(0) {}
["Student_Marks2"] => string(2) "50"
}
function getValues($dataArray,$strKey="")
{
global $arrFinalValues;
if(is_array($dataArray))
{
$currentKey = $strKey;
foreach($dataArray as $key => $val)
{
if(is_array($val) && !empty($val))
{
getValues($val,$currentKey.$key."_");
}
else if(!empty($val))
{
if(!empty($strKey))
$strTmpKey = $strKey.$key;
else
$strTmpKey = $key;
$arrFinalValues[$strTmpKey]=$val;
}
}
}
}

Categories