Определение того, какие данные указывают на приращение PHP - PullRequest
0 голосов
/ 08 февраля 2012

Я создал массив с 10 отметками времени с интервалом в 1 день:

$data_points = array();
$now = time();
$one_day = 60 * 60 * 24;

for($i = 1; $i <= 10; ++$i) {
  $key = $now - ($one_day * $i);
  $data_points[$key] = 0;
}

print_r($data_points);

Array
(
    [1328642414] => 0
    [1328556014] => 0
    [1328469614] => 0
    [1328383214] => 0
    [1328296814] => 0
    [1328210414] => 0
    [1328124014] => 0
    [1328037614] => 0
    [1327951214] => 0
    [1327864814] => 0
)

Теперь у меня есть массив задач, которые запускались в разное время за последние 10 дней, я хочу посмотреть, в какой деньмоя задача выпала на

Я собирался пройтись по каждой $data_point и посмотреть, больше ли время начала, чем текущий день и меньше, чем следующий, затем увеличить эту точку данных

, есть ли лучший способсделать это?

Спасибо

Ответы [ 4 ]

1 голос
/ 08 февраля 2012

Ну, чтобы сократить время поиска, вы можете поместить свои данные в двоичное дерево поиска, а не в простой массив.

То, стоит ли эта проблема, зависит от того, насколько велик ваш набор данных. Конечно, вам также придется периодически перебалансировать дерево, добавляя новые даты.

0 голосов
/ 24 февраля 2013

Я знаю, что этот вопрос старый, но так как нет никаких принятых ответов, и кажется, что это забавный вопрос - вот и мы!

Исходя из вашего вопроса, ваш алгоритм имеет Big O из O(10n), где n - количество задач. Это означает, что это довольно эффективно по сравнению со многими вещами. Как уже указывалось, бинарное дерево поиска было бы быстрее с O(log(n)), однако его реализация не стоила бы сэкономленного времени при обработке. Тем не менее, вы можете сделать его немного более эффективным и получить в результате O(n), используя что-то вроде:

$now = time();
$oneDay = 86400; //60 * 60 * 24
foreach($tasks as $task) {
    //assuming now that $task is the timestamp of the task
    //extra paranthesis added for easier reading
    $dif = $now - ($oneDay * ceil(($now - $task) / $oneDay));
    $data_points[$dif]++;
}

Математика в diff следующая. $now-$task - это разница между двумя временными метками в секундах, которую мы делим на $oneDay, чтобы получить количество дней в прошлом, в течение которых выполнялась задача. Теперь, предполагая, что $now является началом нового дня, и если событие произошло всего 12 часов назад, оно было «вчера», мы используем ceil, чтобы округлить его до следующего целого числа, чтобы «.5» стало «1». ». Оттуда мы умножаем на $oneDay, чтобы получить количество секунд прошедших дней - для работы с ранее созданным массивом $data_points. Затем мы берем этот результат и вычитаем его из $now, снова для работы с вашим массивом $data_points. Этот результат дает нам временную отметку, которую мы можем использовать, которая совпадает с отметкой в ​​созданном вами массиве, и мы используем ее как «ключ» для нее и увеличиваем ее соответственно.

Это избавит вас от необходимости перебирать весь массив $data_points для каждой задачи и, таким образом, уменьшит его сложность с O(10n) до O(n).

В любом случае, я надеюсь, что ответ поможет объяснить, почему ваша формула не настолько неэффективна, но показывает, как сделать ее немного более эффективной.

0 голосов
/ 08 февраля 2012

Я думаю, что есть лучший метод.

Предполагая, что у вас есть метки времени запуска задачи в массиве, алгоритм будет выглядеть примерно так:

for each task starting timestamp
    timestamp <- $now - timestamp // you will obtain task age in seconds
    timestamp <- timestamp / (60*60*24) // you will obtain task age in days
    // round resulting timestamp with a precision of 0 if you want to obtain the task age in integer days.
end for each

Таким образом, вы будете зацикливаться только на одном массиве. Это будет дешевле, чем ваш метод.

Очевидно, что если ваши задачи поступают из базы данных SQL, в SQL найдется лучшее решение.

0 голосов
/ 08 февраля 2012

Вы можете использовать Класс DateTime

$now = new DateTime();
$task = new DateTime('2012-02-20');
$interval = $taks->diff($now);
echo 'Here is the position you need:' . $interval->format('%R%a days');

** Обновлен, чтобы избежать использования DateTime, как указано в комментарии **

$now = date('Ymd');
$task = date('Ymd',$tasktime);
$interval = $task - $now;

Интерваложидаемый номер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...