【发布时间】:2014-01-09 23:14:13
【问题描述】:
我无法找出算法...
我有一长串 GPS 数据,它们以 1 秒的间隔记录时间、速度、距离。假设距离为米,速度为米/秒。可能有超过 2 小时的数据,或 7200 个点。这里的“时间”字段主要仅供参考。
因此,前 5 秒将是类似这样的值,其中 [1-5] 是秒。
$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)
);
我想将其转换为以 1 米为间隔列出的数据,例如 [1-6] 为米。
$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)
);
当然,这可以在没有时间字段的情况下完成。我在计算时遇到了麻烦,因为它绝对不是一对一的。如果我们从 7200 秒的数据开始,我们可能会根据所覆盖的距离(多于或少于 7200 米)得到更多或更少的数据。
编辑(2014 年 1 月 10 日)
以下是这两种方法的实际实现。我实际上很难决定我更喜欢哪种方法,迭代或递归方法。我可能会使用迭代
方法 1,迭代(@Ezequiel Muns,我做了非常小的修改):
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;
}
方法 2,递归(@Nathaniel Ford 伪代码,我是实际代码):
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);
}
【问题讨论】:
-
告诉我们更多关于您尝试过的内容?哪里失败了?
标签: php algorithm time distance