I have some data that looks something like this...
+----------+----------+----------+
| Column 1 | Column 2 | Column 3 |
+----------+----------+----------+
| Red | Blue | Green |
| Yellow | Blue | Pink |
| Black | Grey | Blue |
+--------------------------------+
I need to go through this data and find the 3 most common colours.
The raw data is in CSV and there's likely to be thousands more rows. (link)
What's the best way of doing this?
There's no magic... one row at time, one column at time.
And count each color.
Loop through all the values while keeping a count of each one of them in an array (word => count). After you've done that, find the keys with the highest values.
If the number of possible colors is manageable, just to use an associative array:
$histo = array();
//foreach cell
$color = ??; //however you're getting a cell's value
if(!isset($histo[$color]))
$histo[$color] = 1;
else
$histo[$color]++;
//end loop
//reverse sort by value
$histo = arsort($histo);
//now the first three colors in $histo are the most common ones.
If you're doing the processing in PHP and not a database, and the file contains purely color names, I'd go with something like:
$colors = array();
$fh = fopen('data.txt');
while($row = fgetcsv($fh)) { // omitting length/delimiter arguments
foreach($row as $field) {
$colors[$field]++;
}
}
fclose($fh);
$colors = arsort($colors); // sort in decescending order
After that the top 3 colors will be the first elements in $colors.
Related
I have 3 set of checkboxes in my form and I designed it in such a way that if one is checked, the 3 checkboxes for a particular product will be checked. Which means on submission, the 3 set of checkboxes (itemQuantities[],itemIds[] and sectionIds[]), when I convert them to array using
$item_quantities = $_POST['itemQuantities'];
$item_ids = $_POST['itemIds'];
$section_ids = $_POST['sectionIds'];
They 3 arrays must contain the same number of elements. How can I insert the values of these arrays in one table with one element of the first array into one column, the first element of the second array into the next column, the first element of the third array into the third column and like that.... The number of rows will be the number of elements in one array (Since all arrays have equal elements). For instance:
$array1 = array(1,2,3);
$array2 = array(4,5,6);
$array3 = array(7,8,9);
In the database, I want to have:
| col1 | col2 | col3 |
----------------------
| 1 | 4 | 7 |
| 2 | 5 | 8 |
| 3 | 6 | 9 |
How can I achieve this. I have tried using nested foreach loop but it's not working. Any help will be appreciated. Thanks
Iterate over one of them and use the index of the first on the last two arrays.
foreach($_POST['itemQuantities'] as $key => $value) {
echo $value . PHP_EOL . $_POST['itemIds'][$key] . PHP_EOL . $_POST['sectionIds'][$key];
}
col1, col2, col3 is usually a bad db design, I would reconsider that if that is not pseudo names.
if all variables have the same length you can just loop only one array and use the key to another array
<?php
$array1 = array(1,2,3);
$array2 = array(4,5,6);
$array3 = array(7,8,9);
for ($i=0; $i < count($array1); $i++) {
echo "value in Row ".($i+1)." is : ".$array1[$i].",".$array2[$i].",".$array3[$i]." ";
}
?>
I have a table (items) in my DB and it looks like this:
--------------------------------------
| id | name | price | buyer | status |
--------------------------------------
| 1 item1 10 Bob requested |
| 2 item2 20 Bob requested |
| 3 item3 10 Tom requested |
--------------------------------------
I'm trying to query the data and then sort it, lump it together, and display it by name. If 2 names are the same it'll group it into one div in my HTML, and if they are different it'll group it into a different div. Basically each group of names is its own div whether there is 0 or 20 names that are the same. So far I queried my data like so
$request_data_query = $db->prepare("SELECT * FROM items WHERE status = 'requested' GROUP BY buyer");
$request_data_query->execute();
while($fetch = $request_data_query->fetch(PDO::FETCH_ASSOC)) {
then I was trying to compare results to see if they match
if ($fetch['buyer'] === $fetch['buyer']) {
//Same name HTML code here
} else {
// Single person HTML
}
}
That code isn't sorting the way I thought it would. That prints 2 separate divs for the duplicate name and doesn't print the single person. I'm not quite sure what else to do.
You can use something like this. One that this isn't an exact match for your use, but is based on your examples.
// this goes before your loop
$previousBuyer = '';
// then inside your loop
if ($previousBuyer === $fetch['buyer']) {
//Same name HTML code here
} else {
// Single person HTML
}
$previousBuyer = $fetch['buyer'];
You'll need to account for the first buyer you check.
I have two rows of data - always just two rows, but there could be a maximum of around forty columns. The column names are different on a case by case basis, but here is a representative example:
id | height | width | colour | in_stock | featured | on_sale
------------------------------------------------------------
1 | 30 | 20 | black | yes | no | yes
2 | 30 | 25 | red | yes | yes | no
I want to get all of the differences between those two rows into an array so that I can log what was changed from row 1 to row 2.
I thought it array_diff() would do the job!
So I cheerfully chucked array_diff() at it thus:
//Simplified queries for the example
$sql1 = "SELECT * FROM table WHERE id = 1";
$rs1 = $conn->Execute($sql1);
$rs1 = $rs1->fields;
$sql2 = "SELECT * FROM table WHERE id = 2";
$rs2 = $conn->Execute($sql2);
$rs2 = $rs2->fields;
//Build first array
foreach($rs1 as $key => $value){
$data1[$key] = $value;
}
//Build second array
foreach($rs2 as $key => $value){
$data2[$key] = $value;
}
//Find the differences
$theDifferences = array_diff($data1, $data2);
//Loop through the differences logging the changes
foreach($theDifferences as $field => $value){
echo "Change found for ".$field."!";
}
Why that doesn't work.
This "looked like" it was working. Since many columns contain long strings, colour names, dates etc, so when one changed it was duly pushed into the differences array. The problem was (of course) that the multiple "yes" or "no" columns did not behave as I had expected. Thus the result of the code above, for the table example is:
colour, width
It is not "seeing" the featured or on_sale columns as changed because the data1 array AND the data2 array both contain no's and yes's.
I suppose I need to compare on a key by key basis? Something like the opposite of array_diff_key()? But here I am stuck.
I also considered if this could be done solely with the SQL query, which would I suppose be more efficient, but that is way beyond my SQL ability.
Thanks in advance.
I think you're very nearly there. Maybe something like this after your queries:
$theDifferences = array();
foreach($rs1 as $key => $value){
if ($rs2[$key] != $value){
$theDifferences[$key] = $value;
}
}
As for SQL, you can use an EXCEPT to get a list of rows which are different between two queries, but you'd still have to loop through the keys and look for nulls - which doesn't save you a whole lot.
I know how to solve this in a non-elegant, non-practical way, meaning sending requests, one by one, for each value in specified column that is shared and then handle all data from that specific output, then, do the same for another value, etc., etc. But I was wondering if someone out there thought of an ELEGANT and PRACTICAL way, which would mean all this is handled by one single PHP function.
Basically, I have this table:
location | title | description | quantity
============|===========|=============|==========
shelf | apple | red | 2
drawer | banana | yellow | 4
shelf | kiwi | green | 2
cupboard | lemon | yellow | 1
fridge | melon | orange | 3
drawer | peach | orange | 1
And what I eventually want is to create a jQuery pie chart that tells me what percentage of title is in each location. But before that I need a function that outputs shelf => 4 (2+2), drawer => 5 (4+1), etc., etc.
So, the question is, is there an elegant, practical way to make this happen? Meaning, to retrieve all rows but group together all data by location and, then, sum each location's quantity to be later on turned into a percentage for the pie chart?
Thanks!
select location, sum (quantity) as sum_quantity from table group by location;
and later using $rows as result from query above,
function prepareForChart ($rows) {
$ret = array();
$total = 0;
foreach ($rows as $el) $total += $el["sum_quantity"];
foreach ($rows as $el) {
$ret[] = array(
$el["location"] => $el["sum_quantity"],
"percentage" => 100 * $el["sum_quantity"]/$total,
);
}
return $ret;
}
This should work
SELECT location, SUM(quantity) as total_quantity
FROM table
GROUP BY location
I have a database table like below:
id | igroup | title | url | text
1 | gr1 | Title 1 | urltoimage1 | text1
2 | gr1 | Title 2 | urltoimage2 | text2
3 | gr2 | Title 3 | urltoimage3 | text3
4 | gr2 | Title 4 | urltoimage4 | text4
I mean, i want to have an multidimensional array (for above structure) like below;
$result[gr1] = [Title 1|urltoimage1][Title 2|urltoimage2]
$result[gr2] = [Title 3|urltoimage3][Title 4|urltoimage4]
Finally, I'll send this $result array to page via JSON.
So, in my page I'll arrange these values for classified image gallery, like:
Group 1(caption text)
--------
image1 image2 (clickable images)
Group 2(caption text)
--------
image3 image4 (clickable images)
Edit: i corrected group field by igroup.
Question revised.
You will need to fetch the results using the ORDER BY statement added to your query.
SELECT id, igroup, title, url, text
FROM images
ORDER BY igroup;
Warning:
Please, don't use mysql_* functions to write new code. They are no longer maintained and the community has begun the deprecation process. See the red box?
Instead, you should learn about prepared statements and use either PDO or MySQLi. This article should give some details about deciding which API to use. For PDO, here is a good tutorial.
Example code:
$result = mysql_query(THE_STATEMENT_ABOVE);
$groups = array();
while ( $row = mysql_fetch_assoc($result) )
$groups[ $row['igroup'] ][] = $row;
This will build up a nice $groups array. To parse the array created above, you might either use Iterators or simple foreach constructs.
foreach ( $groups as &$one_group ) {
print("Group 1: <br>");
foreach ( $one_group as &$one_image ) {
// Here you have the contets of the previously fetched $row rows of the result.
print('' .$one_image['title']. '<br>');
}
}
This will give you a nice output like this below:
Group 1:
Image 1 (clickable)
Image 2 (clickable)
Group 2:
Image 3 (clickable)
Image 4 (clickable)
No longer applies: Also, you should refrain from using GROUP as a field name, as it is one of the reserved MySQL words.
Edit: I have also corrected the field name to igroup.