In short, I'm downloading from the category_id, product_id, and active activity tag. The idea is that like all products assigned to a particular category_id have a value of 0, I display the echo "empty", otherwise "products contains", but the foreach loop instead passes through the product id and displays empty + category_id once, passes through $ status and displays So many echo, how many records are active.
The query is ok - I know I should not perform logical operations on arrays, but the database is structured so that I have no output.
$result = array();
foreach ($products as $detail) {
$cid = $detail['category_id'];
$pid = $detail['product_id'];
$status = $detail['active'];
$result[$cid][$pid] = $status;
$multiplier = $result[$cid][$pid];
$counter = count($result[$cid]);
$multiplier2 = 1;
$multiplier = $multiplier * $multiplier2;
echo '$status: ' .$multiplier. " | ";
if ($multiplier == 0) {
echo '$cid: '.$cid.' | empty <br />';
} else {
echo '$cid: '.$cid.' | products contains <br />';
}
}
Duplicate cause, but I do not know how to change the code in this code
Array
(
[0] => Array
(
[product_id] => 1
[0] => 1
[category_id] => 221
[1] => 221
[active] => 0
[2] => 0
)
[1] => Array
(
[product_id] => 2
[0] => 2
[category_id] => 221
[1] => 221
[active] => 0
[2] => 0
)
)
$result array
Array
(
[221] => Array
(
[1] => 0
[2] => 0
)
)
#EDIT
Currently, the function returns something like this
enter image description here
And based on this array, it should be something like - as you can see 1437 has => 1 so the category is not empty
enter image description here
It sounds like you are trying to isolate what is and is not empty from a scattered list (it does sound like you might be able to do a better query though). See if this iteration helps filter.
function getCategoryActivity($products)
{
$store = array();
foreach($products as $detail) {
$cid = $detail['category_id'];
$pid = $detail['product_id'];
# If the cid is not already stored, store it
if(!isset($store[$cid]))
$store[$cid] = $detail['active'];
else {
# If it's already set to active, ignore it
if(!empty($store[$cid]))
continue;
else
# Store it if not currently active
$store[$cid] = $detail['active'];
}
}
# Send back the filtered array
return $store;
}
# Fetch the filtered array
$sorted = getCategoryActivity($products);
$sorted should give you a list of categories now that have activity in them and not in them. You can iterate one more time using array_map() or another foreach() to echo what you want. I have no idea what you are trying to do with that multiplier part so I ignored it.
I have this sort of string that come from my database after many use of CONCAT().
1, AA, 6, 10; 1, Z, 1, 5; 2, AE, 1, 5; 2, AF, 6, 10; 3, X, 1, 5; 3, Y, 5, 10
In order to have something clear, let's say this :
The large string is made of multiple substring, all ending by a ;
Each substring is made of four elements :
A first number. Let's call it the Group
A letter or group of letters. They are called the Section
A second number. We will call it From
A third and last number. We will call it To
Using this code
$data = "1, AA, 6, 10; 1, Z, 1, 5; 2, AE, 1, 5; 2, AF, 6, 10; 3, X, 1, 5; 3, Y, 5, 10";
echo $data;
$ret = array_map (
function ($_) {return explode (', ', $_);},
explode (';', $data)
);
I get the following multidimensional array
Array
(
[0] => Array
(
[0] => 1
[1] => AA
[2] => 6
[3] => 10
)
[1] => Array
(
[0] => 1
[1] => Z
[2] => 1
[3] => 5
)
[2] => Array
(
[0] => 2
[1] => AE
[2] => 1
[3] => 5
)
[3] => Array
(
[0] => 2
[1] => AF
[2] => 6
[3] => 10
)
[4] => Array
(
[0] => 3
[1] => X
[2] => 1
[3] => 5
)
[5] => Array
(
[0] => 3
[1] => Y
[2] => 5
[3] => 10
)
)
I want to end with a multidimensional array that looks like that :
Array
(
[0] => Array
(
[0] => 1
[1] => Array
(
[0] => Z
[1] => 1
[2] => 5
)
[2] => Array
(
[0] => AA
[1] => 6
[2] => 10
)
)
[1] => Array
(
[0] => 2
[1] => Array
(
[1] => AE
[2] => 1
[3] => 5
)
[2] => Array
(
[1] => AF
[2] => 6
[3] => 10
)
)
[2] => Array
(
[0] => 3
[1] => Array
(
[1] => X
[2] => 1
[3] => 5
)
[2] => Array
(
[1] => Y
[2] => 6
[3] => 10
)
)
)
I don't know what's the best method to do it in order to get this result nor if it's possible without too complex operations.
What's the best approach to get the final result ? Should I work on the "raw" multidimensional array or should I work from the string from the beginning ?
Merging arrays with same Group
First, I want to merge substring starting with the same Group value. The rest of each string then become another array inside the newly created array.
I think I can do this by parsing the initial array (Or maybe the string itself ?) and pushing the results in a new one, merging the data in the same time.
In my example, it has been done to the six starting arrays that are now grouped into three arrays.
Sorting using the From and To values
After my substrings with the same Group value are combined into arrays, I want to sort these arrays so the To value of a sub-array is always smaller to the From value of the next one.
The initial string are always generated with the following rules :
There will never be overlapping From and To values like that : 1,5 - 4,7. It would be either 1,4 - 5,7 or 1,5 - 6,7
There will never be missing number in a sequence so you will never have something like 1,3 - 5,7
The From and To value of the same array can be the same. So you can get : 1,4 - 5,5 - 6,7
That's why 1, AA, 6, 10; 1, Z, 1, 5; has been sorted to Z, 1, 5 followed AA, 6, 10. Is there a PHP function that can do this kind of sorting (By comparing values with a different key) or should I create my own ?
Also, if you think that I should totally change the way I want to do this (Using multidimensional arrays...) and you have some ideas, go ahead and share them. I'm also here to learn new way to do things.
Edition concerning Database structure
As stated by #deceze, it may be easier to construct my initial string differently during my SQL query. I have tried it but I'm probably not skilled enough to get what I want. My database looks like that :
Database Structure
As you can see, all the rows are linked by a MasterID. This is because I'm doing a 1 to n query on multiple table.
So far, my query looks like that (I removed all the unnecessary stuff from it) :
SELECT s.MasterID,
GROUP_CONCAT(CONCAT( CONCAT( CONCAT( CONCAT( CONCAT(
s2d.Group, ', '),
s2d.Section, ', '),
s2d.From),', '),
s2d.To) SEPARATOR '; ') AS Concatstuff,
FROM table1 AS s
JOIN table2 AS s2d
ON s2d.MasterID = s.MasterID
WHERE MasterID = $MasterID (A PHP variable)
Because of the 1 to N relation, I don't know how to make this differently. Maybe I could keep it simpler and perform two queries instead of one. In the first query, I get the information from table1 and in the second query, the informations from table2.
But if you know a way to do all of that in only one query, I'm eager to learn how you can do this !
I'd recommend modifying your MySQL query before making many PHP changes.
That massive list of concats will grow quite large, eventually you may even need to adjust the MySQL config setting for GROUP_CONCAT() since it'll truncate after a certain length.
Instead, we can keep the GROUP_CONCAT() and group specifically on individual masterid / group combinations with a GROUP BY. Additionally, GROUP_CONCAT() has an ORDER BY attribute which should solve the sorting issue:
SELECT
s.MasterID,
s2d.`group`,
GROUP_CONCAT(
s2d.`section`, ',', s2d.`from`, ',', s2d.`to`
ORDER BY `from`, `to`
SEPARATOR ';'
) AS Concatstuff
FROM
table1 AS s
JOIN table2 AS s2d
ON s2d.MasterID = s.MasterID
GROUP BY
s.MasterID, s2d.`group`
WHERE
s.MasterID = $MasterID;
This should give us data similar to:
MasterID group Concatstuff
2 1 z,1,5;aa,6,10
2 2 ae,1,5;af,6,10
2 3 x,1,5;y,6,10
Assuming you've retrieved this from the database and have it stored in an array named $results, we can iterate over it like:
$final_groups = array();
foreach ($results as $group) {
// your original `array_map()` logic:
$split_group = array_map(function($_) {
return explode(',', $_);
},
explode(';', $group['Concatstuff'])
);
// ... any other processing you want to do
// store the results:
$final_groups[$group['group']] = $split_group;
}
Note: to explicitly answer your question
Is there a PHP function that can do this kind of sorting
Yes, usort():
function sort_group($a, $b) {
// [1] = 'from'
// [2] = 'to'
if ($a[1] == $b[1]) {
if ($a[2] == $b[2]) {
return 0;
}
return ($a[2] < $b[2]) ? -1 : 1;
}
return ($a[1] < $b[1]) ? -1 : 1;
}
usort($split_group, 'sort_group');
You can customize the comparison logic within sort_group() to match whatever you want it to be. Above, I have it sorting on both from and to =]
Trying to give a general answer without writing your code for you:
For each group, you would set use the group number as index for the contained data.
For each group, you will write its group index into the element with index string prefix plus the number zero: $ret1[$group_number]['d0'] = $group_number;. It will get overwritten every time you add stuff to the group.
Then add the group content with some string index appropriate for sorting. I would propose producing an index using sprintf(), like $idx = sprintf('d%05.1f%05.1f', $from, $to);, so the group number will always be sorted ahead. Again here the prefix. Add it with $ret1[$group_number][$idx] = $group_array;.
Once you have completed this for all input data, run over it for sorting and finishing:
Iterate over all groups in $ret1, sort them by keys and remove the keys with array_values(). Add them to a new array with $ret[] = ....
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.
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']);
}
I am Using PHP and Mysql, Apachhe
I Have an Array
Array
(
[2] => Array
(
[0] => 6
[1] => 2
)
[1] => Array
(
[0] => 6
[1] => 2
)
)
Here The middle container is the Document ID and the final children are userids, Here I am looking for a way to find a method to count the common user ids among all the different Documents. I also need it specified that a particular user id available in which documentids...
could Some one guide me to achieve this?
Thanks in Advance,
OM
$unique_users = array();
foreach ($docs as $doc_id => $users)
{
foreach ($users as $user_id)
{
if (!isset($unique_users[$user_id]))
$unique_users[$user_id] = array($doc_id);
else
$unique_users[$user_id][] = $doc_id;
}
}
echo count($unique_users); // number of users
var_dump($unique_users[1]); // list of documents user_id #1 is in
Add all the ids from the first element to an array. Then continue to loop through the other elements and keep only the ids that are also in the current element.