I'm mainly programming in language that used for business systems, and there is a useful built-in function that can sum an array. For example, we've got array like this:
red | 1
red | 1
green | 1
orange | 2
orange | 1
orange | 1
blue | 1
After using summarizing function we get
red | 2
green | 1
orange | 4
blue | 1
Is it equivalent function in php?
UPD.
$array = array('red'=>1,'red'=>2,'green'=>1....);
In php
red | 1
red | 1
green | 1
orange | 2
orange | 1
orange | 1
blue | 1
This kind of array is not possible. PHP array can not have multiple index keys with the same name. It will override the previous one.
As said, an array like
array('red'=>1,'red'=>2,'green'=>1....);
is not possible. Try it and make a print_r. You will see that there is only one red entry with value 2 (or what ever the last value is). The last one will overwrite the previous ones.
Depending on how you create the array, you can either sum the value on the fly, e.g.
for(...) {
if(!isset($array[$color])) {
$array[$color] = 0;
}
$array[$color] += $value;
}
or create a multidimensional array:
$array = array(
'red'=> array(1,2),
'green'=> array(1),
...
);
You can then array_map to loop over it and compute the sums of each entry with array_sum:
$newarray = array_map('array_sum', $array);
Your initial array should contain only values. You can use array_values() for that. After that you can count the values with array_count_values()
http://php.net/manual/en/function.array-count-values.php
supposed you have array like this:
$array = array(
'red | 1',
'red | 1',
'green | 1',
'orange | 2',
'orange | 1',
'orange | 1',
'blue | 1'
);
You can process it this way:
<?php
//process the array data
$temp_output = array();
foreach( $array as $raw)
{
list($name, $value) = array_map('trim', explode("|", $raw));
if( !isset($temp_output[ $name ] ) )
$temp_output[ $name ] = (int)$value;
else
$temp_output[ $name ] += (int)$value;
}
//now, print the value
foreach( $temp_output as $key => $data)
{
echo "{$key} | {$data}\n";
}
?>
Related
Here's a sample of data
Date | Source | Amount
-----------------------
01A | S1 | 12
01A | S4 | 2
01A | S7 | 134
02A | S1 | 126
03A | S4 | 10
02A | S7 | 0
02A | S1 | 3
02A | S4 | 4
02A | S7 | 5
The resulting array needs to look like:
Array
(
[01A] => Array
(
[S1] => 12
[S4] => 2
[S7] => 134
)
[02A] => Array
(
[S1] => 126
[S4] => 10
[S7] => 0
)
[03A] => Array
(
[S1] => 3
[S4] => 4
[S7] => 5
)
)
I've tried looking at pages such as PHP Adding multiple associative arrays to new array based on key, PHP multiple arrays to one associative array and Merge multiple associative arrays to a single array of associative arrays and playing around with code as below (not using the same data - but same theory) but it's not producing what I need. The code below just shows A and B
$array = Array();
$a=array( "ABC" => array("A"=>"RED","B"=>"GREEN"));
$b=array( "ABC" => array("C"=>"BLUE","D"=>"YELLOW"));
$array = $a + $b;
echo '<pre>';
print_r($array);
echo '</pre>';
KISS
$result = array();
foreach($rows as $row)
{
if(!isset($result[$row['Date']])) $result[$row['Date']] = array();
$result[$row['Date']][$row['Source']] = $row['Amount'];
}
Assuming you already have the data in the $input array, the code is as easy as:
$result = array();
foreach ($input as $row) {
$date = $row['Date'];
if (! array_key_exists($date, $result)) {
$result[$date] = array();
}
$result[$date][$row['Source']] = $row['Amount'];
}
If you don't have the data in $input but you fetch it from the database just replace the line:
foreach ($input as $row) {
with something that matches your data retrieval loop, f.e.:
while ($row = mysqli_fetch_assoc($result)) {
I need to insert data to a table.. the data come from different sources. The following are my code.
$title = array(Book A, Book B, Book C);
$number = array(2,1,4);
$lines = array(Maria, Smith, Abner);
for($i=1; $i<count($lines); $i++)
{
print '<tr>';
print '<td>'.$title[$i].'</td>';
print '<td>P'.$number[$i].'</td>';
print '<td>['.$lines[$i].']</td>';
print '<td></td>';
print '</tr>';
}
Seems not working :/ the array not display properly in my table.
I'm expecting output as follows:
------------------------------------------------
| Title | No | Lines | Remarks |
------------------------------------------------
| Book A | 2 | Maria | |
| Book B | 1 | Smith | |
| Book C | 4 | Abner | |
------------------------------------------------
at the moment.. I get the following output:
------------------------------------------------
| Title | No | Lines | Remarks |
------------------------------------------------
| Book A | 2 | Maria | |
| | | Smith | |
| | | Abner | |
------------------------------------------------
If your arrays has different keys you can 'reset' them to be zero-based. Just use $array = array_values($array). Quote from manual
array_values() returns all the values from the array and indexes the array numerically.
After this you code will work. This is how your example can be modified:
$title = array('Book A', 'Book B', 'Book C');
$number = array("a" => 2, "b" => 1, "c" => 4);
$lines = array('Maria', 'Smith', 7 => 'Abner');
/* At this point you have some arrays with unknown keys.
It can be [0 => item, 1 => item2] or ['name' => item, 'name2' => item2]
or even with skipped keys [0 => item, 7 => item2]
*/
// Reset keys for all arrays. Now all arrays will contain keys 0, 1, 2 etc.
$title = array_values($title);
$number = array_values($number);
$lines = array_values($lines);
for($i = 0; $i < count($lines); $i++) // Note, arrays now are zero-based, you must start from $i = 0
{
print '<tr>';
print '<td>'.$title[$i].'</td>';
print '<td>P'.$number[$i].'</td>';
print '<td>['.$lines[$i].']</td>';
print '<td></td>';
print '</tr>';
}
you just put i=0; because array started from 0 index and try following code may it help u.
<?php $title = array('Book A','Book B','BookC');$number = array('2','1','4');$lines = array('Maria','Smith','Abner');for($i=0;$i<count($lines); $i++){print '<tr>';print '<td>'.$title[$i].'</td>';print '<td>P'.$number[$i].'</td>';print'<td>['.$lines[$i].']</td>';print '<td></td>'; print '</tr>'; } ?>
There's a neat trick to merging separate arrays with array_map() if you pass null as the first argument, followed by the arrays you want merged.
As quoted in Example #4 in the docs:
An interesting use of this function is to construct an array of arrays, which can be easily performed by using NULL as the name of the callback function
Using your example for context:
<?php
$titles = ['Book A', 'Book B', 'Book C'];
$numbers = [2,1,4];
$lines = ['Maria', 'Smith', 'Abner'];
// create an 'array of arrays'
$rows = array_map(null, $titles, $numbers, $lines);
var_dump($rows);
Yields:
array (size=3)
0 =>
array (size=3)
0 => string 'Book A' (length=6)
1 => int 2
2 => string 'Maria' (length=5)
1 =>
array (size=3)
0 => string 'Book B' (length=6)
1 => int 1
2 => string 'Smith' (length=5)
2 =>
array (size=3)
0 => string 'Book C' (length=6)
1 => int 4
2 => string 'Abner' (length=5)
You can then iterate over it pretty easily, like so:
foreach ($rows as $row) {
list($title, $number, $line) = $row;
printf('<tr><td>%s</td><td>%s</td><td>%s</td></tr>',
$title, $number, $line);
}
This should give you something like:
<tr><td>Book A</td><td>2</td><td>Maria</td></tr>
<tr><td>Book B</td><td>1</td><td>Smith</td></tr>
<tr><td>Book C</td><td>4</td><td>Abner</td></tr>
A useful side-effect of this approach is that your arrays do not have to be the same length; null will be used where applicable to pad out any "missing" values.
Another quick example:
<?php
$letters = range('a', 'd'); // ['a', 'b', 'c', 'd']
$numbers = range(1, 3); // [1, 2, 3]
$merged = array_map(null, $letters, $numbers);
var_dump($merged);
Yields:
array (size=4)
0 =>
array (size=2)
0 => string 'a' (length=1)
1 => int 1
1 =>
array (size=2)
0 => string 'b' (length=1)
1 => int 2
2 =>
array (size=2)
0 => string 'c' (length=1)
1 => int 3
3 =>
array (size=2)
0 => string 'd' (length=1)
1 => null
Hope this helps :)
You can try modifying you code as follow:
foreach($lines as $z => $value)
{
print '<tr>';
print '<td>'.$title[$z].'</td>';
print '<td>P'.$number[$z].'</td>';
print '<td>['.$value.']</td>';
print '<td></td>';
print '</tr>';
}
I found that the array index for all my array is not in sequential.
eg: $title =
array[0] = Book A
array[5] = Book B
array[9] = Book C
So, that is probably the reason why it is not display accordingly. I cannot use function 'for'. However, I cannot re-number the index because its the key for me to continue with next module/function.
So, I tried the following code.. but seems something missing..
$i=0;
if (!empty($title)){
foreach($title as $key => $value){
$y = $number[$key];
if ($i<count($lines))
{ $z = $lines[$i];
$i+1;
}
print '<tr>';
print '<td>'.$value.'</td>';
print '<td>'.$y.'</td>';
print '<td>['.$z.']</td>';
print '<td></td>';
print '</tr>';
}
}
The following is the output that I get. Now array for $lines that didn't display properly.
------------------------------------------------
| Title | No | Lines | Remarks |
------------------------------------------------
| Book A | 2 | Maria | |
| Book B | 1 | Maria | |
| Book C | 4 | Maria | |
------------------------------------------------
I have CSV list with team names in it (this is one row):
Teams
Red
Green | Red | Yellow
Red
Yellow | Green | Yellow
Red
Green
Yellow | Yellow | Red
Red
Green
Red
Yellow
I need to be able to count each individual color and count top 4
and number of times they appear.
How can I do that? For example if i try using:
$teams = file('count.csv');
$count[] = (array_count_values($colors));
print_r($count);
I get:
Array ( [0] => Array ( [Teams ] => 1
[Red ] => 5 [Green | Red | Yellow ] => 1 [Yellow | Green | Yellow ] => 1 [Green ] => 2 [Yellow | Yellow | Red ] => 1 [Yellow] => 1 ) )
Which is not very useful. And afrewards how could I compare the valies to one another to get top 4?
Any tricks known how to make this happen? Thank you in advance!
OK another try:
$inputfile = 'count.csv';
$inputHandle = fopen($inputfile, "r");
while (($data = fgetcsv($inputHandle, 1024, ",")) !== FALSE) {
$teams = $data[0];
$teams = explode('|', $teams);
}
$count[] = (array_count_values($teams));
print("<pre>".print_r($count, true)."</pre>");
I get
Array
(
[0] => Array
(
[Yellow] => 1
)
)
What am I doing wrong?
If I understand correctly, you've got one row of data, with | as the delimiter.
Here's a very crude quick'n'dirty solution.
What I would do is first use strpos() and substr() to get the colors, and use a switch-case to increment counters for each color. To get the top 4, create an array to hold four strings, insert the first four colors, and then compare the remaining colors to each value in the array, overwriting values in the array if the color you're comparing has a higher count than any value in the array.
This sounds a bit confusing, so let me know if you'd like me to write some sample code demonstrating this.
I have a table "exercise_results". People put in their results at the beginning and then two months later put in their results to see how much they improved. Their beginning set has the exercise_type_id of "1" and the end set has the exercise_type_id of "2".
I need a way to display this out into a HTML table that looks like this:
a foreach loop, but that's with single rows. I'm having trouble combining two rows into one. I think this may be as simple as some kind of MySQL join? We identify each person by their person_unique_id.
Here are my fields:
id | person_unique_id | person_name | exercise_type_id | mile_running_time | bench_press_weight_lbs | squat_weight_lbs | date_of_exercise_performed
Sample rows:
1 | J123 | John Smith | 1 | 8 | 200 | 300 | 2010-03-20
2 | J123 | John Smith | 2 | 7 | 250 | 400 | 2010-05-20
3 | X584 | Jane Doe | 1 | 10 | 100 | 200 | 2010-03-20
4 | X584 | Jane Doe | 2 | 8 | 150 | 220 | 2010-05-20
I've tried a few solutions but I'm lost. Any help would be great. Thanks!
EDIT:
In response to the comment below, I would hope for some data like:
array 0 =>
array
'Exercise' =>
array
'person_unique_id' => string 'J123'
'person_name' => string 'John Smith'
'begin_mile_running_time' => string '8'
'end_mile_running_time' => string '7'
1 =>
array
'Exercise' =>
array
'person_unique_id' => string 'X584'
'person_name' => string 'Jane Doe'
'begin_mile_running_time' => string '10'
'end_mile_running_time' => string '8'
You can use GROUP_CONCAT() to get a two rows result like this:
SELECT person_unique_id, person_name,
group_concat( mile_running_time ) AS miles,
group_concat( bench_press_weight_lbs ) AS bench,
GROUP_CONCAT( squat_weight_lbs ) AS squat
FROM exercise_result
GROUP BY person_unique_id
Your result will be like:
J123 | John Smith | 8,7 | 200,250 | 300,400
X584 | Jane Doe | 10,8 | 100,150 | 200,220
And then you can use php explode with the result fields to get the results for each type.
Extract the whole table, or whichever rows are interesting to you, sort on person id, compare person id of each row with the next to see if there is a result to print for all columns in your HTML table. If not, jump to the next and leave the fields blank(or some other solution, maybe ignore persons who have not filled in both fields?).
My PHP skills are limited, so no code example.
$query = mysql_query("select ...your data");
while ($row = mysql_fetch_assoc ($query) ) {
if ($row['exercise_type_id']==1)
$exe1[]=$row;
else
$exe2[]=$row;
}
print_r($exe1);
print_r($exe2);
from what I've understood
edit:
try this
$query = mysql_query("select ...your data");
while ($row = mysql_fetch_assoc ($query) ) {
$rows[]=array('Exercise'=>$row);
}
print_r($rows);
If you are ordering on person_unique_id then exercise_type_id, you can do this. If you have two rows for everyone, you can leave out the if (only use the else):
for( $i = 0; $i < count($exercise_results); $i++ )
{
$first = $exercise_results[$i];
if( !isset($exercise_results[$i+1])
|| $first['person_unique_id'] != $exercise_results[$i+1]['person_unique_id' ) {
$second = array(
'person_name'=>$other['person_name'],
'mile_running_time' => null // fill in the rest with defaults (like null)
);
} else {
$second = $exercise_results[$i+1];
$i++; // skip ahead one, since you've already used the second result.
}
// perform your normal printing, but use $beginning and $end to get the respective results
}
Please help me to create an array from a field of my DB. That field has records separated by comma. Below is the illustration:
ID | article_title_fld | article_tags_fld |
----------------------------------------------------------------------
1 | Learn PHP | PHP, coding, scripting |
3 | Javascript Tutorial | Javascript, scripting, tutorial |
4 | Styling with CSS | CSS, tutorial, web design |
I want to collect all records in the article_tags_fld then put it into 1 array. Perhaps I named it $array1, and the print out as below:
Array
(
[0] => PHP
[1] => coding
[2] => scripting
[3] => Javascript
[4] => scripting
[5] => tutorial
[6] => CSS
[7] => tutorial
[8] => web design
)
$array1 = array();
$result = mysql_query("SELECT article_tags_fld FROM MY_TABLE");
while ($row = mysql_fetch_assoc($result)) {
$array1 = array_merge($array1, array_map('trim', explode(",", $row['article_tags_fld'])));
}
explode will split a string by a delimiter.
array_merge will combine two arrays.
array_map will apply trim to all elements.
trim will remove any white space on either side of your tags.
Actually, I would normalize the table into multiple tables first.
articles
article_ID | article_title_fld |
----------------------------------------
1 | Learn PHP |
3 | Javascript Tutorial |
4 | Styling with CSS |
tags
tag_ID | tag_title_fld |
------------------------
1 | PHP |
2 | coding |
3 | scripting |
4 | Javascript |
5 | tutorial |
6 | CSS |
7 | web design |
article_tags
article_ID | tag_ID |
---------------------
1 | 1 |
1 | 2 |
1 | 3 |
3 | 4 |
3 | 3 |
3 | 5 |
4 | 6 |
4 | 5 |
4 | 7 |
and then in the PHP
$array1 = array();
$result = mysql_query("
SELECT tag_title_fld
FROM tags
JOIN articles_tags USING(tag_ID)
ORDER BY article.article_ID
");
foreach($result as $row) {
$array1[] = $row['tag_title_fld'];
// With count. See below for the query it goes with
// $array2 = array();
// $array2['tag'] = $row['tag_title_fld'];
// $array2['count'] = $row['tag_count'];
// $array1[] = $array2;
}
Of course, if you just wanted a list of the tags without duplicates, you'd use this query instead.
SELECT tag_title_fld
FROM tags
and if you wanted them with a count of how often they're used:
SELECT tag_title_fld, COUNT(*) AS tag_count
FROM tags
JOIN articles_tags USING(tag_ID)
GROUP BY tag_title_fld
UPDATED
you can do also this way by using mysql_fetch_Array
$array1 = array();
$result = mysql_query("SELECT ID , article_tags_fld FROM my_table");
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {
$array1[] = $row['article_tags_fld'];
// OR
// $array1[] = $row[1];
}
ADDED:
in one line:
// use this version to behave as in your example..
$array1 = array_map('trim',explode(',',implode(',',$array1)));
// use this version with array_unique for a non duplicate way...
$array1 = array_unique(array_map('trim',explode(',',implode(',',$array1))));
DISPLAY:
print_r( $array1 );
Array
(
[0] => PHP
[1] => coding
[2] => scripting
[3] => Javascript
[4] => scripting
[5] => tutorial
[6] => CSS
[7] => tutorial
[8] => web design
)
This should output everything.
$pdo = new PDO( /* CONNECTION */ );
$stmt = $pdo->query( 'SELECT article_tags_fld FROM TABLENAME' );
function mapFunc( $row ){ return explode( ',', $row[ 0 ] ) }
$all = array();
foreach( array_map( 'mapFunc', $stmt->fetchAll() ) as $row )
{
$all = array_merge( $all, $row );
}
// $all now holds all of the values.
You should normalize your database table so that you don't have comma-separated values in your rows.
mysql_ functions should no longer be used, so I'll demonstrate mysqli's object-oriented syntax.
If your database values are consistently comma-space separated, then explode() is fine. If you might have leading or trailing spaces in your article_tags_fld values, then you can TRIM() that in your SQL. If you might not have spaces after each comma, then you can explode the strings with preg_split() using a pattern like /, */.
The result set object from a mysqli query is iterable by foreach(), so you can safely avoid making iterated fetch() calls to access the column of data.
By pushing the exploded values with the spread operator (...), the result array will be flat.
If you want to remove duplicate values from the result, you can call array_unique() on the result array after the loop is finished.
Modernized Code: (Full MYSQL + PHP Demo)
$result = [];
foreach ($mysqli->query("SELECT article_tags_fld FROM MY_TABLE") as $row) {
array_push($result, ...explode(', ', $row['article_tags_fld']));
}
var_export(array_unique($result));