array_values_database and k means - php

I used K-means algorithm. The function get 2 parameters: an array that consists of product average cost per user and an integer that represents the number of clusters ( kmeans($pin, 2) ).
I want to put into the database the letter A if the user buys expensive products and B if not. The function that return the results is the following:
function kmeans_get_cluster_values($clusters, $data) {
$n = array(); $values = array();
foreach($clusters as $dataKey => $cluster) {
$values[$cluster][] = $data[$dataKey].' <br/>';
}
return $values;
}
The output is:
Array (
[1] => Array (
[0] => 346.98
[1] => 214.42
[2] => 280.26
)
[0] => Array (
[0] => 46.99
[1] => 13.78
)
)
Numbers 346.98, 214.42 and 280.26 are in the first cluster and numbers 46.99 and 13.78 are in the second cluster. The problem is that I can't find a way to separate this array.
For example I want to insert into my MySQL database the first cluster that consist of 3 numbers and then the second cluster and so on. As a matter of fact I want to insert into the database the letters A or B for the number of cluster.

Related

Find the maximum and parent value in an array

I searched many thread but i can't find this solution
I have this Array
Array
( [0] => [1] => Array ( [0] => 2019-01-11T23:30:00CET [1] => -12.6 ) [2] => [3] => Array ( [0] => 2019-01-11T23:20:00CET [1] => -12.5 ) [4] => [5] => Array ( [0] => 2019-01-11T23:10:00CET [1] => -12.6 ) [10] => [11] => Array ( [0] => 2019-01-11T22:40:00CET [1] => -12.4 )
I found the path to have the maximum or minimum value ( Column [1] ) from this Array but i need to find the relative Parent
(example the minimum -12.6 is in the [1][0] as 2019-01-11T22:20:00CET)
of this two values that are show in the first column ( Column[0] )
Thanks
If you use array_column() to extract the second column of your data, then you can use min() or max() with that array to pick which one you want. This code then extracts the ones that match using a foreach() and if to check if it matches (not exactly sure what you want as output, but this should help)...
$source = [["2019-01-11T23:30:00CET", -12.6],
["2019-01-11T23:20:00CET", -12.5],
["2019-01-11T23:10:00CET", -12.6]
];
$extract = min(array_column($source, 1)); // or use max()
$output = [];
foreach ($source as $key => $element) {
if ( $element[1] == $extract ) {
// Matches, so add to output
$output[$key] = $element[0];
}
}
print_r($output);
will give
Array
(
[0] => 2019-01-11T23:30:00CET
[2] => 2019-01-11T23:10:00CET
)
You could use array_filter() to extract the matching rows, but a foreach() is enough for a straightforward thing like this (IMHO).
If there is a possibility of blank values or strings in the value column, this may confuse the min() as it will consider the values and compare them as strings, to ensure they are all compared as numbers you can add...
$values = array_map("floatval", array_column($source, 1));
$extract = min($values); // or use max()
The array_map("floatval",... goes through the list and converts them all to float values.
Also, here's a generalized algorithm-sketch for "finding the max in some array", expressed as pseudo-code:
"Leave quietly" if the array is empty, or throw an exception.
Otherwise, assume that the first element in the array is the biggest one.
Now, loop through the remaining elements, testing if each one is, in fact, bigger than the "biggest one" that you have so far. If so, select it as the "biggest."
When the loop is finished, return your answer.
Now – this is what a geek would call "an O(n) algorithm," which is to say that its execution-time will be "on the order of" the number of elements in the array. Well, if this is a "one-off" requirement, that's fine. Whereas if what you actually want to do is to get "more than one" max-element, sorting the array (once, then holding on to the sorted result ...) becomes significantly better, because the sort is going to be O(log(n)) ... "on the order of some logarithm of the number of elements," ... and the subsequent cost of "popping off" elements from that sorted array becomes non-existent.
There are other ways to do it, of course – trees and such - but I've already blathered-on too long here.

Joining arrays in PHP (like MySQL join)

I would like to join two arrays in PHP, the same as I could do with MySQL join left. I have two arrays:
$db_products from database (it has id and sku fields)
$csv_prices from a CSV file (it has sku and price fields)
$db_products: (it has 4000 items)
Array
(
[0] => Array
(
[id] => 1012
[sku] => asd123
)
[N] => Array
(
[id] => ...
[sku] => ...
)
)
$csv_prices: (it has 8000 items)
Array
(
[0] => Array
(
[sku] => asd123
[price] => 15.50
)
[N] => Array
(
[sku] => ...
[price] => ...
)
)
The join is $db_products[$key][sku] = $csv_prices[$key][sku]. To find the matching pair, I am doing loops in loops which result in 4000 * 8000 check for match. It consumes a lot of energy and time, and I want to be more efficient.
I could lower by 10% the used time, by unset()-ing the used $csv_prices[$key], but I want to be more efficient.
If you loop through the $csv_products array once and set the SKU as the array key then you won't have to exponentially loop through that array each time you have a new product to find its match.
Instead, you just loop through the product array and use isset() to see if it exists or not.
This way you'll only need to do 1x count($db_products) and 1x count($csv_prices) repetitions, instead of count($db_products) * count($csv_prices) reps (12 thousand vs 32 million).
The concept could be considered to be similar to indexing in databases - you use the key you want to look up as the array key/index, meaning you don't have to loop through the array every time to find the record you want.
Example:
// Reindex the CSV array to use SKU as the key
$reindexed = array();
foreach ($csv_prices as $values) {
$reindexed[$values['sku']] = $values;
}
unset($csv_prices);
// Join the prices
foreach ($db_products as &$product) {
$sku = $product['sku'];
$product['price'] = isset($reindexed[$sku]) ? $reindexed[$sku]['price'] : '';
}
Of course, you won't see a remarkable difference in performance until you start using large data sets - the change would be noticeable exponentially as the data sets grow.
This is working fine for me
function left_join_arrays($key, $array1, $array2) {
$i=0;
foreach ($array1 as $arr1) {
foreach ($array2 as $arr2) {
if ($arr1[$key]==$arr2[$key]) {
foreach(array_keys($arr2) as $key2){
if ($key != $key2) {
$array1[$i][$key2]=$arr2[$key2];
}
}
continue;
}
}
$i++;
}
return $array1;
}

If value exists in one PHP array, add value to second array

I have two PHP arrays. One contains a group name and another contains a pay wage value.
$group_wages_array = Array ( [0] => 1 [1] => 4 [2] => 1 [3] => 3 );
This means there are four employees on the schedule. Two are assigned to group 1, another to group 4 and the last to group 3.
The second array is as follows:
$tot_wages_array = Array ( [0] => 500 [1] => 44 [2] => 80 [3] => 11.25 );
This is a sample array of each employee's wage. Both arrays are constructed in order as values are added in a mysql while loop as it pulls the info from the database.
Later on down the line, I combine the two arrays to get one array where the key is the group number and the value is the total wages for that group:
$combined_group_wages = array_combine($group_wages_array, $tot_wages_array);
This works like a charm EXCEPT for when more than one employee is assigned to the same group. These arrays are built in a mysql while loop as it loops through each employee's info:
array_push($tot_wages_array, $totemp_wages_sch); // Add their wage to the array
array_push($group_wages_array, $emp_data['group_id']); // Add their group to the array
Instead of just pushing the data to the array, I need to do this... I know the english but I don't know how to code it:
If $emp_data['group_id'] exists as value in $group_wages_array, add nothing to this array but get the key. Add $totemp_wages_sch to $tot_wages_array where key = group_wages_array key
I know it sounds more like an SQL query but I have to keep the keys and values in order so that they can be combined later in the page. If I can get this to work right, The arrays shown in the example would be:
$group_wages_array = Array ( [0] => 1 [1] => 4 [2] => 3 );
$tot_wages_array = Array ( [0] => 580 [1] => 44 [2] => 11.25 );
$combined_group_wages = array_combine($group_wages_array, $tot_wages_array);
$combined_group_wages = Array ( [1] => 580 [4] => 44 [3] => 11.25 );
...I've got to make this work using PHP. Any ideas?
I came up with a solution based on a combination of two of the answers submitted below. Here it is if it can help someone:
if(in_array($emp_data['group_id'], $group_wages_array)){
$key = key($group_wages_array);
$tot_wages_array[$key] += $totemp_wages_sch;
} else {
array_push($group_wages_array, $emp_data['group_id']);
array_push($tot_wages_array, $totemp_wages_sch);
}
This should do it:
$group_wages_array = array(1, 4, 1, 3);
$tot_wages_array = array(500, 44, 80, 11.25);
$combined_group_wages = array();
for ($i=0; $i<count($group_wages_array); $i++) {
$group = $group_wages_array[$i];
if (array_key_exists($group_wages_array[$group], $combined_group_wages)) {
$combined_group_wages[$group] += $tot_wages_array[$i];
} else {
$combined_group_wages[$group] = $tot_wages_array[$i];
}
}
print_r($combined_group_wages);
Yields:
Array
(
[1] => 580
[4] => 44
[3] => 11.25
)
But I recommend that you just switch to using objects to better represent your data.
If I could see the entirety of the code that would help a lot, but here's your English converted to php. Show me more code and I can perfect it, until then try this ->
if(in_array($emp_data['group_id'], $group_wages_array)){
$key = key($group_wages_array);
$tot_wages_array[$key] = $totemp_wages_sch;
} else {
array_push($group_wages_array, $emp_data['group_id']);
}

PHP Array insert into MySQL table as individual rows

I am trying to insert multiple rows in a MySQL table from PHP arrays. I managed with with help of other members to get set of values in a pair of brackets but when i try to insert this i get "Error: Column count doesn't match value count at row 1" I donot know where am i going wrong. my codes are as below: (The number of values i get vary according to user input)
$docno1=array();
$serialno = array();
$acc_name = array();
$debit = array();
$credit = array();
for ($i=1;$i<=$rowcount;$i++)
{
//echo 'Accountname'.$i.' :'.($_GET['accname'.$i]).'<br>';
$docno1 [] = ($_GET['docno']);
array_unshift($docno1,"");
unset($docno1[0]);
$serialno [] = $i;
array_unshift($serialno,"");
unset($serialno[0]);
$acc_name[] = ($_GET['accname'.$i]);
array_unshift($acc_name,"");
unset($acc_name[0]);
$debit[] = ($_GET['DrAmount'.$i]);
array_unshift($debit,"");
unset($debit[0]);
$credit[] = ($_GET['CrAmount'.$i]);
array_unshift($credit,"");
unset($credit[0]);
}
$sum_dr = array_sum ($debit);
$sum_cr = array_sum ($credit);
echo ' values of $multi<br>';
$multi = array(
($docno1),
($serialno), //Array for a row of fields
($acc_name),
($debit),
($credit),
($docno1)
);
print_r($multi);
$new = array();
foreach($multi as $key=>$value) {
$new[] = "'".implode("','", $value)."'";
}
echo '<br>Values of $new <br>';
print_r($new);
$query = "(".implode("), (",$new).")";
echo $query.'<br>';
mysql_query("INSERT INTO docitems (`docno`,`itemno`,`accountname`,`debit`,`credit`, `picrefno`) VALUES ".$query.";") or die('Error: ' . mysql_error());
echo "Inserted successfully";
die;
The results i get are :
values of $multi
Array
(
[0] => Array
(
[1] => 3434
[2] => 3434
)
[1] => Array
(
[1] => 1
[2] => 2
)
[2] => Array
(
[1] => Lemon
[2] => Kidney Beans
)
[3] => Array
(
[1] => 20
[2] => 10
)
[4] => Array
(
[1] => 0
[2] => 0
)
[5] => Array
(
[1] => 3434
[2] => 3434
)
)
Values of $new
Array
(
[0] => '3434','3434'
[1] => '1','2'
[2] => 'Lemon','Kidney Beans'
[3] => '20','10'
[4] => '0','0'
[5] => '3434','3434'
)
('3434','3434'), ('1','2'), ('Lemon','Kidney Beans'), ('20','10'), ('0','0'), ('3434','3434')
Error: Column count doesn't match value count at row 1
mysql_query("INSERT INTO docitems (`docno`,`itemno`,`accountname`,`debit`,`credit`, `picrefno`) VALUES ".$query.";") or die('Error: ' . mysql_error());
You are trying to insert something into 6 fields, so that $query string must have 6 values in it, or you get this error.
You have a lot of $query's that are 2 values. And that's not 6
It looks to me as if you are mapping your array the wrong way round. You're trying to add two records with six fields each, but what you're actually putting into the SQL statement are six records with two fields each.
This is why MySQL is complaining -- because you've told it you want to update six fields, but in each of the records you've given it, you've only specified two fields.
You need to build your array differently.
I assume that $docno1, $serialno, $acc_name, $debit and $credit will always all have the same number of array elements (it appears from your code that you are assuming this, so I'll follow you in your assumption).
In that case, you need to build your array something like this:
$multi = array();
foreach($docno1 as $key=>value) {
$multi[] = array(
$docno1[$key],
$serialno[$key], //Array for a row of fields
$acc_name[$key],
$debit[$key],
$credit[$key],
$docno1[$key])
}
Replace the block in your code where you set $multi with this, and your program should work.
Look at what print_r($multi) looks like now, and you'll see the difference.
(note, there are more efficient ways of writing your whole program than this, but I've focused on giving you a drop-in replacement for this specific bit, to help show you where you were going wrong, rather than simply rewriting the whole program for you)
Hope this helps.
If the error is occurring when trying to insert a row to your table, try specifying the list of fields, in the insert query -- this way, the number of data in the values clause will match the number of expected columns.
Else, MySQL expects six columns : it expects the specific inserts -- for which you didn't specify a value.

Getting all possible combinations of N items in X Groups

I have a list of Groups that can vary in number, with Items in these groups that also vary in number. I've been racking my head over a way to get all possible combinations of 1 Item from every Group.
Bonus: I also need all combinations of not having every items from a group.
I've seen and done what was mentioned before, but that requires knowing the number of groups to begin with.
To be more specific about what I'm doing, I would like to generate products with exact pricing based off product options. Here's an example list:
So it would generate products like:
UV Coating, Qty 500, Color 4:0
UV Coating, Qty 500, Color 4:1
etc...
Each of these Groups has an ID, and each item has a Group_Item_ID. So I can put them in an array such as:
$selections[1][...] // 1 = Coating
$selections[2][...] // 2 = Quantity
// ... = all selected Items in group
Hope I explained it well enough. I'm just not able to wrap my head around how to do this when the number of Groups are variable also.
Here's an example array for the groups and their items:
Array
(
[0] => Array
(
[0] => 2
[1] => 3
)
[1] => Array
(
[0] => 10
[1] => 11
[2] => 12
)
[2] => Array
(
[0] => 16
[1] => 17
)
[3] => Array
(
[0] => 19
[1] => 20
)
)
Try this:
function c($groups, $prefix='')
{
$result = array();
$group = array_shift($groups);
foreach($group as $selected) {
if($groups) {
$result = array_merge($result, c($groups, $prefix . $selected. ' '));
} else {
$result[] = $prefix . $selected;
}
}
return $result;
}

Categories