I have a multidimensional array which is created by a MySQL query which collects results based on a number of groups and sums. The array is below.
I'm interested in the costtotal and hitcount for each type of 'ad_type', 'click_status' and 'link_status' variation.
The possible values of the 3 types of variable are known:
i.e.
ad_type 0 / 1
click_status 2 / 3
link_status 1 / 2
I would like to create a new array based on the results of each combination.
I'm guessing a search or split would do it but I'm not having much luck.
How would I go about doing this?
Array
(
[0.261346210037681] => Array
(
[costtotal] => 0.0015
[hitcount] => 1
[ad_type] => 0
[click_status] => 2
[link_status] => 1
)
[0.190427019438173] => Array
(
[costtotal] => 0.001
[hitcount] => 1
[ad_type] => 0
[click_status] => 3
[link_status] => 1
)
[0.563596305962276] => Array
(
[costtotal] => 0.007
[hitcount] => 5
[ad_type] => 1
[click_status] => 2
[link_status] => 1
)
[0.893211513658251] => Array
(
[costtotal] => 0
[hitcount] => 3
[ad_type] => 1
[click_status] => 2
[link_status] => 2
)
[0.209184847035617] => Array
(
[costtotal] => 0.004
[hitcount] => 2
[ad_type] => 1
[click_status] => 3
[link_status] => 1
)
[0.73545002260753] => Array
(
[costtotal] => 0
[hitcount] => 1
[ad_type] => 1
[click_status] => 3
[link_status] => 2
)
)
If I fully understand what you want, then this code should satisfy you:
function generateClickCounterInfo() {
return array(
'costTotal' => 0.0,
'hitCount' => 0
);
}
function generateLinkStatusStructure() {
return array(
1 => generateClickCounterInfo(),
2 => generateClickCounterInfo()
);
}
function generateClickStatusStructure() {
return array(
2 => generateLinkStatusStructure(),
3 => generateLinkStatusStructure()
);
}
function generateAdTypeArrayStructure() {
return array(
0 => generateClickStatusStructure(),
1 => generateClickStatusStructure()
);
}
function getClickCounterReport(array $data) {
$result = generateAdTypeArrayStructure();
foreach ($data as $key => $value) {
$adType = $value['ad_type'];
$clickStatus = $value['click_status'];
$linkStatus = $value['link_status'];
if (!isset($result[$adType])
|| !isset($result[$adType][$clickStatus])
|| !isset($result[$adType][$clickStatus][$linkStatus])) {
throw new Exception(
"Input data does not conform to expected format. " .
"ad_type = {$adType}, click_status = {$clickStatus}, link_status = ${linkStatus}"
);
}
$costTotal = $value['costtotal'];
$hitCount = $value['hitcount'];
$result[$adType][$clickStatus][$linkStatus]['costTotal'] += $costTotal;
$result[$adType][$clickStatus][$linkStatus]['hitCount'] += $hitCount;
}
return $result;
}
And than getClickCounterReport($data) (where $data is data provided by you) will produce following array: http://pastebin.ubuntu.com/607464/
P.S. Knowing disadvantages:
No OOP (but these functions will be easy to transform to methods)
Magick numbers (0, 1, 2, 3 etc)
No array splitting is necessary. Simply create the variables that will store the totals for each of the permutation you want to measure and iterate through your array. Add to appropriate variables based upon the value you observe in ad_type, click_status, and link_status.
Related
Given an array of arrays like this:
$array = array(
0 => array (
0 => 35,
1 => 30,
2 => 39
),
1 => array (
0 => 20,
1 => 12,
2 => 5
),
...
n => array (
0 => 10,
1 => 15,
2 => 7
),
);
I have the need to find the entry in the array which is closer to given parameters
find($a, $b, $c) {
//return the closer entry to the input
}
For closer entry I mean the entry which has closer values to the ones gave in input, e.g. passing (19, 13, 3) it should return $array[1]
The way in which I do the calculation at the moment is looping through the whole array, keeping a variable $distance which starts from -1, and a temporary $result variable. For each element I calculate the distance
$dist = abs( subarray[0] - $a ) + abs ( subarray[1] - $b ) + abs( subarray[2] - $c )
and if the calculated distance is equal to -1 or lower than the variable $distance which is out of the loop, I assign the new distance to the varaible and I save the corresponding array in the $result variable. At the end of the loop I end up having the value I need.
Also, one of the values can be empty: e.g. (19, 13, false) should still return $array[1] and the calculation should then ignore the missing parameter - in this case the distance is calculated as
$dist = abs( subarray[0] - $a ) + abs ( subarray[1] - $b );
ignoring the values of subarray[2] and $c.
The problem is, even if my code is working, it took too much time to execute as the size of the array can easily go up to many hundred thousands elements. We are still talking about milliseconds, but for various reasons this is still unacceptable.
Is there a more effective way to do this search in order to save some time?
A custom function - maybe there is a better way but check it out :
In a few words :
Search all the items and find in percentage the difference between the number it checks($mArray[0...3]) and the number you gave($mNumbersToFind[0...3]. Add all the three number's (of each element) possibilities - find the max - keep the position and return the array.
$array = array(
array (
0 => 13,
1 => 15,
2 => 4
),
array (
0 => 20,
1 => 12,
2 => 5
),
array (
0 => 13,
1 => 3,
2 => 15
),
);
$mNumbersToFind = array(13,3,3);
$mFoundArray = find($mNumbersToFind, $array);
echo "mFinalArray : <pre>";
print_r($mFoundArray);
function find($mNumbersToFind, $mArray){
$mPossibilityMax = count($mNumbersToFind);
$mBiggestPossibilityElementPosition = 0;
$mBiggestPossibilityUntilNow = 0;
foreach($mArray as $index => $current){
$maxPossibility = 0;
foreach($current as $subindex => $subcurrent){
$mTempArray[$index][$subindex]['value'] = $subcurrent - $mNumbersToFind[$subindex];
$percentChange = (1 - $mTempArray[$index][$subindex]['value'] / $subcurrent) * 100;
$mTempArray[$index][$subindex]['possibility'] = $percentChange;
$maxPossibility += $percentChange/$mPossibilityMax;
}
$mTempArray[$index]['final_possibility'] = $maxPossibility;
if($maxPossibility > $mBiggestPossibilityUntilNow){
$mBiggestPossibilityUntilNow = $maxPossibility;
$mBiggestPossibilityElementPosition = $index;
}
}
echo "mTempArray : <pre>"; // Remove this - it's just for debug
print_r($mTempArray); // Remove this - it's just for debug
return $mArray[$mBiggestPossibilityElementPosition];
}
Debug Output ($mTempArray) :
mTempArray :
Array
(
[0] => Array
(
[0] => Array
(
[value] => 0
[possibility] => 100
)
[1] => Array
(
[value] => 12
[possibility] => 20
)
[2] => Array
(
[value] => 1
[possibility] => 75
)
[final_possibility] => 65
)
[1] => Array
(
[0] => Array
(
[value] => 7
[possibility] => 65
)
[1] => Array
(
[value] => 9
[possibility] => 25
)
[2] => Array
(
[value] => 2
[possibility] => 60
)
[final_possibility] => 50
)
[2] => Array
(
[0] => Array
(
[value] => 0
[possibility] => 100
)
[1] => Array
(
[value] => 0
[possibility] => 100
)
[2] => Array
(
[value] => 12
[possibility] => 20
)
[final_possibility] => 73.333333333333
)
)
Final Output :
mFinalArray :
Array
(
[0] => 13
[1] => 3
[2] => 15
)
I basically used a concept of proximity (lesser distance total for each array) and returned that. The code was made in a way that can improve very well in so many routines.
PS: I didn't used advanced functions or other things because you are concerned about performance issues. It's most simplest routine I could did in a short period of time.
$array = array(
0 => array (
0 => 35,
1 => 30,
2 => 39
),
1 => array (
0 => 20,
1 => 12,
2 => 5
),
);
$user = array(19,13,3);
function find($referencial, $input){
$totalRef = count($referencial);
if (is_array($referencial)){
for ($i = 0; $i < $totalRef; $i++) {
if (is_array($referencial[$i])){
$totalSubRef = count($referencial[$i]);
$proximity = array();
for ($j = 0; $j < $totalSubRef; $j++) {
$proximity[$i] += abs($referencial[$i][$j] - $input[$j]);
}
if ($i > 0){
if ($maxProximity['distance'] > $proximity[$i]) {
$maxProximity['distance'] = $proximity[$i];
$maxProximity['index'] = $i;
}
} else {
$maxProximity['distance'] = $proximity[$i];
$maxProximity['index'] = $i;
}
}
}
return $maxProximity;
} else {
exit('Unexpected referencial. Must be an array.');
}
}
$found = find($array, $user);
print_r($found);
//Array ( [distance] => 4 [index] => 1 )
print_r($array[$found['index']]);
// Array ( [0] => 20 [1] => 12 [2] => 5 )
I have the following structure for my array which is dynamically generated:
Array
(
[0] => Array
(
[friend_request_sender_id] => 1
[friend_request_date] => 07-08-2014
[friend_request_time] => 11:12:19
[friend_request_recipient_id] => 5
[friend_request_sent] => 1
[friend_request_accepted] => 0
)
[1] => Array
(
[friend_request_sender_id] => 1
[friend_request_date] => 07-08-2014
[friend_request_time] => 11:12:47
[friend_request_recipient_id] => 2
[friend_request_sent] => 1
[friend_request_accepted] => 0
)
)
I would like to update the first array value [friend_request_accepted] => 0 to this: [friend_request_accepted] => 1 which i have achieved by doing the following:
$test = get_user_meta($current_user->ID,'get_user_friends', true );
foreach($test as &$values){
if($values['friend_request_recipient_id'] === '5'){
$values['friend_request_accepted'] = '1';
break; // Stop the loop after we've found the item
}
}
However, i would like to actually save this new value into the database, overwriting the existing value. The array should then look like this:
Array
(
[0] => Array
(
[friend_request_sender_id] => 1
[friend_request_date] => 07-08-2014
[friend_request_time] => 11:12:19
[friend_request_recipient_id] => 5
[friend_request_sent] => 1
[friend_request_accepted] => 1
)
[1] => Array
(
[friend_request_sender_id] => 1
[friend_request_date] => 07-08-2014
[friend_request_time] => 11:12:47
[friend_request_recipient_id] => 2
[friend_request_sent] => 1
[friend_request_accepted] => 0
)
)
How should I do this?
this line doesn't work:
if($values['friend_request_recipient_id'] === '5'){
$values['friend_request_accepted'] = '1';
break; // Stop the loop after we've found the item
}
because
[friend_request_recipient_id] => 5
is an integer I think you just need to sure in condition because '===' is also checked the types of variable.
We have three array something like this but these are dynamic
Array
(
[04/07/2013] => 2
[05/02/2013] => 1
[06/02/2013] => 1
[08/07/2013] => 2
[08/08/2013] => 3
[09/07/2013] => 2
[11/07/2013] => 1
[16/03/2013] => 1
[17/07/2013] => 1
[18/04/2013] => 2
[18/07/2013] => 1
[21/05/2013] => 2
[24/05/2013] => 8
[25/04/2013] => 2
[26/04/2013] => 1
[26/06/2013] => 1
[30/05/2013] => 1
)
Array
(
[01/08/2013] => 42
[02/08/2013] => 2
[03/08/2013] => 3
[07/08/2013] => 29
[09/08/2013] => 4
[10/08/2013] => 4
[11/08/2013] => 31
[19/07/2013] => 4
[20/07/2013] => 4
[22/07/2013] => 13
[23/07/2013] => 69
[29/07/2013] => 4
[31/07/2013] => 5
)
Array
(
[13/02/2013] => 2
[26/04/2013] => 2
[04/06/2013] => 2
[20/06/2013] => 2
[04/07/2013] => 2
[09/07/2013] => 1
[01/08/2013] => 1
[07/08/2013] => 1
[08/08/2013] => 3
)
We want to combine into other array with keys(key must be remain same).If all three array keys has same put it into the same key other wise create a key for and put it value if array has key other wise put it with zero value.
Here we tried for this
$maximum = max($countVisi,$countClic,$countClai);
if($countClic==$maximum){
$maxim = $clickArray;
}elseif($countVisi>=$maximum){
$maxim = $visitArray;
}elseif($countClai>=$maximum){
$maxim = $claimsArray;
}else{
$maxim = $visitArray;
}
we count the maximum index array and foreach the loop like this
foreach($maxim as $key=>$values){
if($visitArray[$key]){
$vv[$key] = $visitArray[$key];
}else{
$vv[$key] = 0;
}
if($clickArray[$key]){
$cc[$key] = $clickArray[$key];
}else{
$cc[$key] = 0;
}
if($claimsArray[$key]){
$kk[$key] = $claimsArray[$key];
}else{
$kk[$key] = 0;
}
$combineArrayNext[$key][] = $vv[$key];
$combineArrayNext[$key][] = $cc[$key];
$combineArrayNext[$key][] = $kk[$key];
//$vvvvv = explode('/' , $key);
//$myKey[$key] = "'".date('d M Y' , strtotime($vvvvv[2]."/".$vvvvv[1]."/".$vvvvv[0]))."'";
}
The problem is that we are getting only according to max array key.It leave the key which are not exits in max array.
Sorry for the less explaining , I think you understand my problem.Please share some idea with us to solve my problem.
Thanks
Hope this code helps you:
$dates = array_merge(array_keys($arr1), array_keys($arr2), array_keys($arr3));
foreach($dates as $date) {
$new_arr[$date] = array('click' => isset($arr1[$date])? $arr1[$date] : 0,
'visit' => isset($arr2[$date])? $arr2[$date] : 0,
'claim' => isset($arr3[$date])? $arr3[$date] : 0 );
}
I would like to sort the following names
Array ( [Jessie] => 2 [Sarah] => 3 [Simon] => 2 [John] => 2 [Kevin] => 1 [Canvasser] => 8 [canvasser] => 11 )
based on the values corresponding to them
I printed the names through the following function
// get canvasser individual names and count houses canvassed
foreach ($canvassers as $key => $value) {
// Add to the current group count if it exists
if ( isset( $canvasser_counts[$value] ) ) {
$canvasser_counts[$value]++;
}
// or initialize to 1 if it doesn't exist
else {
$canvasser_counts[$value] = 1;
}
}
print_r($canvasser_counts);
where $canvassers simply held all the names eg.
$canvassers = array('Jessie', 'Simon', 'Jessie')
Any help would be really appreciated, I have spent so long on this but can't get my head straight to sort the array correctly.
You want to use asort() - http://php.net/manual/en/function.asort.php - to sort the values in ascending order, or arsort() - http://php.net/manual/en/function.arsort.php - to sort in descending order.
Given this PHP:
$vals = array("Jessie" => 2, "Sara" => 3, "Simon" => 2, "John" => 2, "Kevin" => 1, "Canvasser" => 8, "canvasser" => 11 );
print_r($vals); // current order
asort($vals); // sort array
print_r($vals); // new order
You will get the following output:
Array
(
[Jessie] => 2
[Sara] => 3
[Simon] => 2
[John] => 2
[Kevin] => 1
[Canvasser] => 8
[canvasser] => 11
)
Array
(
[Kevin] => 1
[Jessie] => 2
[John] => 2
[Simon] => 2
[Sara] => 3
[Canvasser] => 8
[canvasser] => 11
)
I can't seem to wrap my head around this.
I am given an array in PHP that looks something like this:
array (
0 => array (
0 => 50,
1 => 0.80
),
1 => array (
0 => 300,
1 => 0.50
),
2 => array (
0 => 600,
1 => 0.30
),
3 => array (
0 => 1000,
1 => 0.20
),
4 => array (
0 => 4000,
1 => 0.10
)
);
An array of arrays where the first index of the inner array represents a quantity while the second index represents a price.
I want to import this data into my database, but in a specific way.
I have specific quantities that I like to keep track of that are defined by the following array:
array(10,100,500,1000,5000,10000);
I then want to make the original array more fine tuned to quantities and prices that I would like to see. So in this particular example, I would like an array that looks like this:
array (
0 => array (
0 => 100,
1 => 0.80
),
1 => array (
0 => 500,
1 => 0.50
),
2 => array (
0 => 1000,
1 => 0.20
),
3 => array (
0 => 5000,
1 => 0.10
)
);
My new array will only contain the specific quantity indexes.
If a quantity exists in the original array, I use that price. If it doesn't exist, I would use the price of the next lowest quantity. If no lower quantity exists, I don't want to see that quantity in the new array.
I have been able to accomplish what I want for the most part with the following code:
function getRelativePrices($pricearray) {
$relativeprices = array();
$types = array(10,100,500,1000,5000,10000);
foreach ($types as $q) {
$new_array = array();
foreach ($pricearray as $index => $array) {
if ($q >= $array[0]) {
$new_array = array($q, $array[1]);
}
}
if (sizeof($new_array)) {
$relativeprices[] = $new_array;
}
}
return $relativeprices;
}
The only problem with the above is that I am getting extra data that I do not want. In the example I provided, I am getting a 5th index/array at the end that looks like:
4 => array (
0 => 10000,
1 => 0.10
)
I don't want this last piece, since I find it redundant considering that I know that 5000 pieces cost $0.10 each, so I can assume that 10000 will cost the same price when "4000" is the highest quantity given in the original array.
So I want to ask for help in removing this last piece.
Also, I was wondering if someone had a better coding method in general for converting this array.
You could just do in your inner foreach:
foreach ($pricearray as $index => $array) {
if ($q >= $array[0]) {
if($q == 10000) { continue; }
$new_array = array($q, $array[1]);
}
}
OK I think this should do the trick. I think the problem was in your comparison... See code:
function getRelativePrices($pricearray) {
$relativeprices= array();
$types = array(10,100,500,1000,5000,10000);
foreach($pricearray as $p) {
$new_array = array();
foreach($types as $t) {
if($p[0] <= $t) {
$new_array = array($t,$p[1]);
break;
}
}
if(sizeof($new_array)) {
$relativeprices[] = $new_array;
}
}
return $relativeprices;
}
Here is an example of my test based on your code examples:
function getRelativePrices($pricearray) {
$relativeprices= array();
$types = array(10,100,500,1000,5000,10000);
foreach($pricearray as $p) {
$new_array = array();
foreach($types as $t) {
if($p[0] <= $t) {
$new_array = array($t,$p[1]);
break;
}
}
if(sizeof($new_array)) {
$relativeprices[] = $new_array;
}
}
return $relativeprices;
}
$test = array (
0 => array (
0 => 50,
1 => 0.80
),
1 => array (
0 => 300,
1 => 0.50
),
2 => array (
0 => 600,
1 => 0.30
),
3 => array (
0 => 1000,
1 => 0.20
),
4 => array (
0 => 4000,
1 => 0.10
)
);
print_r(getRelativePrices($test));
And the output was:
Array
(
[0] => Array
(
[0] => 100
[1] => 0.8
)
[1] => Array
(
[0] => 500
[1] => 0.5
)
[2] => Array
(
[0] => 1000
[1] => 0.3
)
[3] => Array
(
[0] => 1000
[1] => 0.2
)
[4] => Array
(
[0] => 5000
[1] => 0.1
)
)