Parse.com greater than returning duplicates - php

I'm using this PHP parse.com API library to retrieve rows from a table from Parse.
Due to the limit of maximum 1000 rows per request, I'm retrieving them in a for loop like this:
$lastUpdated = null;
$parse = new parseQuery($tableName);
$parseAllResults = array();
$skip = 0;
do {
$index = count($parseAllResults) - 1;
if($skip === 10000) {
$lastUpdated = $parseAllResults[$index]['updatedAt'];
$skip = 0;
}
$parseResults = queryParseCrawlObjects($lastUpdated, $skip);
if (!empty($parseResults)) {
$skip += 1000;
} else {
$skip = 0;
}
$parseAllResults = array_merge($parseAllResults, $parseResults);
} while ($skip > 0);
function queryParseCrawlObjects($parse, $lastUpdated, $skip) {
global $parse;
date_default_timezone_set('UTC');
$parse->orderBy('updatedAt');
if ($lastUpdated != null) {
$parse->whereGreaterThan('updatedAt', $parse->dataType('date', $lastUpdated));
} else {
$parse->whereNotEqualTo('objectId', '');
}
$parse->setLimit(1000);
$parse->setSkip($skip);
$results = $parse->find();
return $results['results'];
}
I'm using the whereNotEqualTo('objectId', ''); restriction as a workaround for a bug in the library, that practically retrieves all the rows, and the skip parameter ro retrieve them in a batch of 1000 rows.
Another limitation of Parse is that it doesn't allow a skip greater than 10.000. So I use the updatedAt field of the last row in the first 10.000 batch, as a restriction for the next rows.
And after the first 10.000 rows, it calls the whereGreaterThan method, that internally adds the gt (greater than) Parse parameter to the curl request.
The problem is that in the second loop step, it returns the same row as the last one from the previous step, and I get an error for duplicate objectId when I try to insert them into a database.
So the array looks something like this:
// first step
$parseAllResults[0] = array('objectId' => 'ihJikHNkjH', ...);
$parseAllResults[1] = array('objectId' => 'sHJKHfddkO', ...);
...
$parseAllResults[9999] = array('objectId' => 'rukBfcaDFR', ...);
// second step
$parseAllResults[10000] = array('objectId' => 'rukBfcaDFR', ...);
$parseAllResults[10001] = array('objectId' => 'gusFGvQWVs', ...);
...
$parseAllResults[19999] = array('objectId' => 'asHppNVAaD', ...);
with the 9999th and 10000th having the rest of the properties equal, so I'm sure it's the same row from Parse retrieved twice.
I don't understand why it does that, since it has a whereGreaterThanOrEqualTo method too, using the gte (greater than or equal to) Parse parameter.
TL;DR
greater than (gt) parameter behaves exactly like greater than or equal to (gte) parameter.

This might fix your issue. Change this part of your code:
if($skip === 10000) {
$lastUpdated = $parseAllResults[$index]['updatedAt'];
$skip = 0;
}
to:
if($skip === 10000) {
$lastUpdated = $parseAllResults[$index]['updatedAt'];
$skip = 1;
}

Related

How to limit duplicate values in an array

First of all, I apologize for my lack of English. I hope you do understand what I'm trying to explain here.
So basically I need to build a function that would limit the number of duplicate values inside an array.
The reason I need to do this is that I'm building a system that would divide numbers into groups and every group has to have the same amount of numbers.
EDIT: Random number represents the group number.
I've written a function do this but for some reason, it is not working properly.
function jagaTiimid($max, $liiget, $tArvLength, $tArv){
$tiimid = []; //Starting array
for($z=0;$z<$liiget;$z++){
$numbers = [];
$rn = randomNumber($tArvLength, $tArv, $numbers); //Generate a random number for a group, etc group 1, group 2, group 3
$mitu = countInArray($tiimid, $rn); //Check how many times that number has occured in array
if($mitu == $max){ //If it equals to maximum number of times then...
$rnUus = randomNumber($tArvLength, $tArv, $numbers); //generate a new random number
while($rnUus == $rn){
$numbers = [];
$rnUus = randomNumber($tArvLength, $tArv, $numbers);
} //loop until the new generated number doesn't equal to old rn.
$tiimid[] = $rnUus; //if it doesn't equal to $rn then push into array
}else{
$tiimid[] = $rn;
}
}
return $tiimid;
}
For some reason the number still occures more than it is suppose to.
Basically how it shouldn't end up is.
As you can see, one group(group 2) occurs more times than other group but it should be equal for both groups.
EDIT: CountInArray();
function countInArray($array, $what) {
$count = 0;
for ($i = 0; $i < count($array); $i++) {
if ($array[$i] === $what) {
$count++;
}
}
return $count;
}
When the first random pick hits a number that is already used $liiget times, the inner loop kicks in, but it does not check whether the newly generated random number already occurs $liiget times.
For efficiency I would keep track of the number of times a number has been used. Also, you could benefit from a safety net, in case there really is no number any more that would not exceed the maximum recurrence.
It is not necessary to have a nested loop. The code would look like this:
function jagaTiimid($max, $liiget, $tArvLength, $tArv){
$tiimid = []; //Starting array
$counts = []; // Helper for quick count
$tries = 0; // Counter to avoid infinite looping
while (count($tiimid) < $liiget && $tries++ < 100) {
$numbers = [];
$rn = randomNumber($tArvLength, $tArv, $numbers); //Generate a random number for a group, etc group 1, group 2, group 3
if (!isset($counts[$rn])) $counts[$rn] = 0; // initialise on first occurence
if ($counts[$rn] < $max) {
$tiimid[] = $rn; // add it to the result
$counts[$rn]++; // ... and adjust the count
$tries = 0; // reset the safety
}
}
return $tiimid;
}
replace while($rnUus == $rn) with while(countInArray($tiimid, $rnUus) >= $max)
– Ilya Bursov

Is there a faster way than array_diff in PHP

I have a set of numbers from MySQL within the range 1000 0000 (8 digits) to 9 999 999 999 (10 digits). It's supposed to be consecutive, but there are missing numbers. I need to know which numbers are missing.
The range is huge. At first I was going to use PHP to do this:
//MySqli Select Query
$results = $mysqli->query("SELECT `OCLC Number` FROM `MARC Records by Number`");
$n_array = array();
while($row = $results->fetch_assoc()) {
$n_array[] = $row["OCLC Number"];
}
d($n_array);
foreach($n_array as $k => $val) {
print $val . " ";
}
/* 8 digits */
$counter = 10000000;
$master_array = array();
/* 10 digits */
while ($counter <= 9999999999 ) {
$master_array[] = $counter;
$counter++;
d($master_array);
}
d($master_array);
$missing_numbers_ar = array_diff ($master_array, $n_array);
d($missing_numbers_ar);
d() is a custom function akin to var_dump().
However, I just realized it would take tons of time for this to be done. At the 15 minute mark, $master_array is being populated with only 4000 numbers.
How can I do this in a quicker way? MySQL-only or MySQL-and-PHP solutions both welcome. If the optimal solution depends on how many numbers are missing, please let me know how so. Tq.
Your d() probably is the cause of slowness, please remove it, and make small changes in your code
while($row = $results->fetch_assoc()) {
$n_array[$row["OCLC Number"]] = 1;
}
and
$missing_numbers_ar = [];
while ($counter++ <= 9999999999 ) {
if (empty($n_array[$counter])) {
$missing_numbers_ar[] = $counter;
}
}
If the following is still slow I would be surprised. I also just noticed it is similar to #Hieu Vo's answer.
// Make sure the data is returned in order by adding
// an `ORDER BY ...` clause.
$results = $mysqli->query("SELECT `OCLC Number`
FROM `MARC Records by Number`
ORDER BY `OCLC Number`");
$n_array = array();
while($row = $results->fetch_assoc()) {
// Add the "OCLC Number" as a key to the array.
$n_array[$row["OCLC Number"]] = $row["OCLC Number"];
}
// assume the first array key is in fact correct
$i = key($n_array);
// get the last key, also assume it is not missing.
end($n_array);
$max = key($n_array);
// reset the array (should not be needed)
reset($n_array);
do {
if (! $n_array[$i]) {
echo 'Missing key:['.$i.']<br />';
// flush the data to the page as you go.
flush();
}
} while(++$i <= $max);

Removing enclosed intervals in an array of intervals in PHP

I have such an array of intervals sorted by the lower bound ($a[$i] <= $a[$i+1] for every $i), key l is lower bound and , key h is upper bound and I'd like to remove all rows with intervals that are enclosed by larger intervals.
$a[0] = array('l' => 123, 'h'=>241);
$a[1] = array('l' => 250, 'h'=>360);
$a[2] = array('l' => 280, 'h'=>285);
$a[3] = array('l' => 310, 'h'=>310);
$a[4] = array('l' => 390, 'h'=>400);
So the result I'd like to get is
$a[0] = array('l' => 123, 'h'=>241);
$a[1] = array('l' => 250, 'h'=>360);
$a[2] = array('l' => 390, 'h'=>400);
This is what I attempted
function dup($a){
$c = count($a)-1;
for ($i = $c; $i > 0; $i --){
while ($a[$i]['h'] <= $a[$i-1]['h']){
unset($a[$i]);
}
}
$a = array_values($a);
}
The first answer which comes in mind was given with different variations by other contributors : for each interval, loop on each interval looking for a larger and enclosing interval. It's simple to understand and to write, and it works for sure.
This is basically n2 order, which means for n intervals we'll do n*n loop turns. There can be some tricks to optimize it :
break'ing when we find an enclosing interval in the nested loop, as in user3137702's answer, because it's useless to continue if we find at least one enclosing interval
avoiding looping on the same interval in the nested loop because we know an interval cant be strictly enclosed in itself (not significant)
avoiding looping on already excluded intervals in the nested loop (can have a significant impact)
looping on intervals (global loop) in ascending width = (h - l) order, because smaller intervals have more chance to be enclosed in others and the earliest we eliminate intervals, the more the next loop turns are effective (can be significant too in my opinion)
searching for enclosing intervals (nested loop) in descending width order, because larger intervals have more chance to be enclosing other intervals (I think it can have a significant impact too)
probably many other things that do not come to mind at the moment
Let me say now that :
optimization does not matter much if we have only few intervals to compute from time to time, and currently accepted user3137702's answer does the trick
to develop the suitable algorithm, it is necessary anyway to study the characteristics of the data that we have to deal with : in the case before us, how is the distribution of intervals ? Are there many enclosed intervals ? This can help to choose from the above list, the most useful tricks.
For educational purposes, I wondered if we could develop a different algorithm avoiding a n*n order which running time is necessarily very quickly deteriorated gradually as you increase the number of intervals to compute.
"Virtual rule" algorithm
I imagined this algorithm I called the "virtual rule".
place starting and ending points of the intervals on a virtual rule
run through the points along the rule in ascending order
during the run, register open or not intervals
when an interval starts and ends while another was opened before and is still open, we can say it is enclosed
so when an interval ends, check if it was opened after one of the other currently open intervals and if it is strictly closed before this interval. If yes, it is enclosed !
I do not pretend this is the best solution. But we can assume this is faster than the basic method because, despite many tests to do during the loop, this is n order.
Code example
I wrote comments to make it as clear as possible.
<?php
function removeEnclosedIntervals_VirtualRule($a, $debug = false)
{
$rule = array();
// place one point on a virtual rule for each low or up bound, refering to the interval's index in $a
// virtual rule has 2 levels because there can be more than one point for a value
foreach($a as $i => $interval)
{
$rule[$interval['l']][] = array('l', $i);
$rule[$interval['h']][] = array('h', $i);
}
// used in the foreach loop
$open = array();
$enclosed = array();
// loop through the points on the ordered virtual rule
ksort($rule);
foreach($rule as $points)
{
// Will register open intervals
// When an interval starts and ends while another was opened before and is still open, it is enclosed
// starts
foreach($points as $point)
if($point[0] == 'l')
$open[$point[1]] = $point[1]; // register it as open
// ends
foreach($points as $point)
{
if($point[0] == 'h')
{
unset($open[$point[1]]); // UNregister it as open
// was it opened after a still open interval ?
foreach($open as $i)
{
if($a[$i]['l'] < $a[$point[1]]['l'])
{
// it is enclosed.
// is it *strictly* enclosed ?
if($a[$i]['h'] > $a[$point[1]]['h'])
{
// so this interval is strictly enclosed
$enclosed[$point[1]] = $point[1];
if($debug)
echo debugPhrase(
$point[1], // $iEnclosed
$a[$point[1]]['l'], // $lEnclosed
$a[$point[1]]['h'], // $hEnclosed
$i, // $iLarger
$a[$i]['l'], // $lLarger
$a[$i]['h'] // $hLarger
);
break;
}
}
}
}
}
}
// obviously
foreach($enclosed as $i)
unset($a[$i]);
return $a;
}
?>
Benchmarking against basic method
It runs tests on randomly generated intervals
basic method works without a doubt. Comparing results from the two methods allows me to predent the "VirtualRule" method works because as far as I tested, it returned the same results
// * include removeEnclosingIntervals_VirtualRule function *
// arbitrary range for intervals start and end
// Note that it could be interesting to do benchmarking with different MIN and MAX values !
define('MIN', 0);
define('MAX', 500);
// Benchmarking params
define('TEST_MAX_NUMBER', 100000);
define('TEST_BY_STEPS_OF', 100);
// from http://php.net/manual/en/function.microtime.php
// used later for benchmarking purpose
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function debugPhrase($iEnclosed, $lEnclosed, $hEnclosed, $iLarger, $lLarger, $hLarger)
{
return '('.$iEnclosed.')['.$lEnclosed.' ; '.$hEnclosed.'] is strictly enclosed at least in ('.$iLarger.')['.$lLarger.' ; '.$hLarger.']'.PHP_EOL;
}
// 2 foreach loops solution (based on user3137702's *damn good* work ;) and currently accepted answer)
function removeEnclosedIntervals_Basic($a, $debug = false)
{
foreach ($a as $i => $valA)
{
$found = false;
foreach ($a as $j => $valB)
{
if (($valA['l'] > $valB['l']) && ($valA['h'] < $valB['h']))
{
$found = true;
if($debug)
echo debugPhrase(
$i, // $iEnclosed
$a[$i]['l'], // $lEnclosed
$a[$i]['h'], // $hEnclosed
$j, // $iLarger
$a[$j]['l'], // $lLarger
$a[$j]['h'] // $hLarger
);
break;
}
}
if (!$found)
{
$out[$i] = $valA;
}
}
return $out;
}
// runs a benchmark with $number intervals
function runTest($number)
{
// Generating a random set of intervals with values between MIN and MAX
$randomSet = array();
for($i=0; $i<$number; $i++)
// avoiding self-closing intervals
$randomSet[] = array(
'l' => ($l = mt_rand(MIN, MAX-2)),
'h' => mt_rand($l+1, MAX)
);
/* running the two methods and comparing results and execution time */
// Basic method
$start = microtime_float();
$Basic_result = removeEnclosedIntervals_Basic($randomSet);
$end = microtime_float();
$Basic_time = $end - $start;
// VirtualRule
$start = microtime_float();
$VirtualRule_result = removeEnclosedIntervals_VirtualRule($randomSet);
$end = microtime_float();
$VirtualRule_time = $end - $start;
// Basic method works for sure.
// If results are the same, comparing execution time. If not, sh*t happened !
if(md5(var_export($VirtualRule_result, true)) == md5(var_export($VirtualRule_result, true)))
echo $number.';'.$Basic_time.';'.$VirtualRule_time.PHP_EOL;
else
{
echo '/;/;/;Work harder, results are not the same ! Cant say anything !'.PHP_EOL;
stop;
}
}
// CSV header
echo 'Number of intervals;Basic method exec time (s);VirtualRule method exec time (s)'.PHP_EOL;
for($n=TEST_BY_STEPS_OF; $n<TEST_MAX_NUMBER; $n+=TEST_BY_STEPS_OF)
{
runTest($n);
flush();
}
Results (for me)
As I thought, clearly different performances are obtained.
I ran the tests on a Core i7 computer with PHP5 and on a (old) AMD Quad Core computer with PHP7. There are clear differences in performance between the two versions on my systems ! which in principle can be explained by the difference in PHP versions because the computer that is running PHP5 is much more powerful...
A simplistic approach, maybe not exactly what you want, but should at least point you in the right direction. I can refine it if needed, just a bit busy and didn't want to leave the question unanswered..
$out = [];
foreach ($a as $valA)
{
$found = false;
foreach ($a as $valB)
{
if (($valA['l'] > $valB['l']) && ($valA['h'] < $valB['h']))
{
$found = true;
break;
}
}
if (!$found)
{
$out[] = $valA;
}
}
This is entirely untested, but should end up with only the unique (large) ranges in $out. Overlaps as I mentioned in my comment are unhandled.
The problem was missing break in the while cycle
function dup($a){
$c = count($a)-1;
for ($i = $c; $i > 0; $i --){
while ($a[$i]['h'] <= $a[$i-1]['h']){
unset($a[$i]);
break; //here
}
}
$a = array_values($a);
}
Here is the code
function sort_by_low($item1,$item2){
if($item1['l'] == $item2['l'])
return 0;
return ($item1['l']>$item2['l'])? -1:1;
}
usort($a,'sort_by_low');
for($i=0; $i<count($a); $i++){
for($j=$i+1; $j<count($a);$j++){
if($a[$i][l]<=$a[$j]['l'] && $a[$i][h]>=$a[$j]['h']){
unset($a[$j]);
}
}
}
$a=array_values($a);
Here is the working code (Tested)
$result = array();
usort($a, function ($item1, $item2) {
if ($item1['l'] == $item2['l']) return 0;
return $item1['l'] < $item2['l'] ? -1 : 1;
});
foreach ($a as $element) {
$exists = false;
foreach ($result as $r) {
if (($r['l'] < $element['l'] && $r['h'] > $element['h'])) {
$exists = true;
break;
}
}
if (!$exists) {
$result[] = $element;
}
}
$result will contain the desired result

Convert Time:[Distance,Speed] data to Distance:[Time,Speed] data

I'm having trouble figuring out an algorithm...
I've got a long series of GPS data that records Time, Speed, Distance, at 1 second intervals. Assume the distance is meters, and speed in m/s. There may be upwards of 2 hours of data, or 7200 points. The "time" field in here is mainly just for reference.
So, the first 5 seconds would be values something like this, with [1-5] being seconds.
$data = array(
1 : array('distance'=>0, 'time'=>'2014-01-09 17:50:00', 'speed'=>0.0),
2 : array('distance'=>2, 'time'=>'2014-01-09 17:50:01', 'speed'=>2.0),
3 : array('distance'=>6, 'time'=>'2014-01-09 17:50:02', 'speed'=>4.0),
4 : array('distance'=>10, 'time'=>'2014-01-09 17:50:03', 'speed'=>4.0),
5 : array('distance'=>12, 'time'=>'2014-01-09 17:50:04', 'speed'=>2.0)
);
I'd like to convert this to data that is listed at 1 meter intervals instead, like this with [1-6] being meters.
$data = array(
1 : array('seconds'=>1.5, 'time'=>'2014-01-09 17:50:01.500', 'speed'=>.666),
2 : array('seconds'=>2, 'time'=>'2014-01-09 17:50:02', 'speed'=>2.0),
3 : array('seconds'=>2.25, 'time'=>'2014-01-09 17:50:02.250', 'speed'=>4.0),
4 : array('seconds'=>2.5, 'time'=>'2014-01-09 17:50:02.500', 'speed'=>4.0),
5 : array('seconds'=>2.75, 'time'=>'2014-01-09 17:50:02.750', 'speed'=>4.0),
6 : array('seconds'=>3, 'time'=>'2014-01-09 17:50:03', 'speed'=>4.0)
);
This can be done w/o the time field of course. I'm having trouble with the calculation, since it definitely isn't 1-to-1. If we start with 7200 seconds of data, we could end up with more or less depending on the distance covered (more or less than 7200 meters).
EDIT (01/10/2014)
Below are the actual implementations of the two methods. I'm actually having trouble deciding which I like better, the iterative or recursive method. I may go with the iterative
METHOD 1, iterative (#Ezequiel Muns, with very minor modifications by me):
function timeToDistance($data) {
if(sizeof($data) == 0){ return; }
$startTime = $data[0]['time'];
$prev = null;
$result = array();
foreach ($data as $secs => $row) {
$row['seconds'] = $secs; // to simplify passing in secs
if ($prev == null) {
// make sure we have a pair
$prev = array( 'distance'=>0 );
}
foreach (distanceRowsBetween($startTime,$prev, $row) as $dist => $distRow) {
$result[$dist] = $distRow;
}
$prev = $row;
}
return $result;
}
function distanceRowsBetween($startTime,$prevRow, $nextRow) {
// Return the by-distance rows that are between $prevRow (exclusive)
// and $nextRow (inclusive)
$rows = array();
$currDist = $prevRow['distance'];
while (true) {
// try to move to the next whole unit of distance
$dDist = ceil($currDist) - $currDist;
$dDist = $dDist == 0.0? 1.0 : $dDist; // dDist is 1 unit if currDist is whole
$currDist += $dDist;
if ($currDist > $nextRow['distance'])
break;
$currSpeed = $nextRow['speed'];
$currSecs = strtotime($nextRow['time']) - strtotime($startTime);
$currTime = $nextRow['time'];
$rows[$currDist] = array(
'speed' => $currSpeed,
'seconds' => $currSecs,
'time' => $currTime,
);
}
return $rows;
}
METHOD 2, recursive (#Nathaniel Ford pseudocode, me actual code):
function data2dist($time_data = array()){
$dist_data = array();
if(sizeof($time_data) == 0){ return $dist_data; }
$start_point = array_shift($time_data);
$start_time = $start_point['time'];
data2dist_sub($start_time, $time_data,$dist_data,$start_point);
return $dist_data;
}
function data2dist_sub($start_time,&$time_data, &$dist_data, $start_point = array()){
if(sizeof($time_data) == 0 && !isset($start_point)){
return;
}
if(sizeof($dist_data) == 0){
$prev_dist = 0;
} else {
$prev_dist = $dist_data[sizeof($dist_data)-1]['distance'];
}
// since distances are accumulating, get curr distance by subtracting last one
$point_dist = $start_point['distance'] - $prev_dist;
if($point_dist == 1){
// exactly 1: perfect, add and continue
$dist_data[] = $start_point;
$start_point = array_shift($time_data);
} else if($point_dist > 1){
// larger than 1: effectively remove 1 from current point and send it forward
$partial_point = $start_point;
$partial_point['distance'] = 1 + $prev_dist;
$dist_data[] = $partial_point;
} else if($point_dist < 1){
// less than 1, carry forward to the next item and continue (minor: this partial speed is absorbed into next item)
$start_point = array_shift($time_data);
if(!isset($start_point)){ return; }
$start_point['distance'] += $point_dist;
}
data2dist_sub($start_time,$time_data,$dist_data,$start_point);
}
You can simplify this by noting that for every contiguous pair of by-time rows you need to calculate 0 or more by-distance rows, and these depend solely on those two by-time rows.
So start with a function to do this simpler calculation, this is a skeleton leaving the calculation of the transformed 'seconds', 'speed' and 'time' values out for simplicity.
function distanceRowsBetween($prevRow, $nextRow) {
// Return the by-distance rows that are between $prevRow (exclusive)
// and $nextRow (inclusive)
$rows = array();
$currDist = $prevRow['distance'];
while (true) {
// try to move to the next whole unit of distance
$dDist = ceil($currDist) - $currDist;
$dDist = $dDist == 0.0? 1.0 : $dDist; // dDist is 1 unit if currDist is whole
$currDist += $dDist;
if ($currDist > $nextRow['distance'])
break;
// calculate $currSecs at distance $currDist
// calculate $currSpeed
// calculate $currTime
$rows[$currDist] = array(
'speed' => $currSpeed,
'seconds' => $currSecs,
'time' => $currTime,
);
}
return $rows;
}
Now that you have this all that remains is iterating over each contiguous pair in the input and accumulate resulting by-distance rows:
function timeToDistance($data) {
$prev = null;
$result = array();
foreach ($data as $secs => $row) {
$row['seconds'] = $secs; // to simplify passing in secs
if ($prev == null) {
$prev = $row; // make sure we have a pair
continue;
}
foreach (distanceRowsBetween($prev, $row) as $dist => $distRow) {
$result[$dist] = $distRow;
}
$prev = $row;
}
return $result;
}
Note in this function I am populating and passing in the current 'seconds' value in the row, to reduce the number of parameters passed into the previous function.
This is a bit of a mind-bender, and there are a couple of edge cases that make it difficult. However, your basic algorithm should boil down to:
Take in an array of by-Time data points
Create a new array of by-Distance data points
Create a first by-Distance data point with 'zero' speed/distance
Pass this to your subfunction
Subfunction (Takes by-Time array, by-Distance array and 'start point')
Take the first by-Time data point and 'add' it to the by-Distance data point, call this 'temp'
Convert to seconds/speed
If distance covered by temp is exactly 1, add this new array to the by-Distance array
If it is more than one, subtract the portion that would equal one
back-calculate distance/speed/time, add to by-Distance array
Recurse into the subfunction, using the remainder as your new start point
If it is less than one
Recurse into the subfunction, using the modified start point as new start point
Note that the sub-function will need to use mutable copies of the arrays: the by-Time array should slowly shrink and the by-Distance array grow. Also, you will want to trampoline the function (rather than use straight recursion) because with 7200 datapoints you will probably have more than that in stack frames, and you run into a potential memory problem.

Function generating Unique Random Values Array

As Mysql rand() is time consuming I am using alternate way using Mysql max() and PHP. I wrote this code for fetching random product_id's:
function RandomUniqueArray($min,$max,$limit){
$random_array = array();
if(isset($limit) && is_numeric($limit)){
for($i=0;$i<$limit;){
$rand_val = mt_rand($min, $max);
if(!in_array($rand_val, $random_array)){
$random_array[] = $rand_val;
$i++;
}
}
}
return $random_array;
}
This works fine as I want each time it gives different result set with different unique values but it takes 6.232 micro seconds.
Ohter I got by Google is:
$random_array = array_rand(array_fill($min,$max, true),$limit);
with takes only 0.101 microseconds but its result set is repeated means. Unique values array is fine but whole set is repeated. Why is it so???
I called both of these by one by one as
$random_array = RandomUniqueArray(1,64000,4);
And
$random_array = array_rand(array_fill(1,64000, true),4);
Thank you.
I made a script,that only takes ̣̣̣+- 4.5E-6.
Try it.
function randomValue($min,$max,$limit)
{
$array = Array();
$MAX = mt_rand($min,$max);
for($i = 0;$i < $limit;$i++)
{
$array[$i] = mt_rand($min,$MAX);
while( is_array($array[$i],$array) ) //To check if exist, if. Make new.
{
$array[$i] = mt_rand($min,$MAX);
}
}
return $array;
}

Categories