За последние 24 часа нас посетили 18366 программистов и 1635 роботов. Сейчас ищут 1683 программиста ...

Сложение отрезков времени.

Тема в разделе "PHP для новичков", создана пользователем Ruslan, 1 авг 2014.

  1. Ruslan

    Ruslan Активный пользователь

    С нами с:
    15 июл 2009
    Сообщения:
    13
    Симпатии:
    0
    Доброго времени суток!
    Столкнулся с одной проблемой, никак не могу решить.
    Есть массив с отрезками времени в unix-формате (в примере обычные числа):
    Код (Text):
    1. Array (
    2. [0] => Array ( [date_in] => 10 [date_out] => 20)
    3. [1] => Array ( [date_in] => 20 [date_out] => 40 )
    4. [2] => Array ( [date_in] => 30[date_out] => 50 )
    5. [3] => Array ( [date_in] => 100 [date_out] => 200 )
    6. [4] => Array ( [date_in] => 110 [date_out] => 250 )
    7. )
    Мне нужно сложить отрезки (если пересекаются) и получить общие. То есть в моем примере будет массив:
    Код (Text):
    1. Array (
    2. [0] => Array ( [date_in] => 10 [date_out] => 50)
    3. [1] => Array ( [date_in] => 100 [date_out] => 250 )
    4. )
    Написал код:
    Код (Text):
    1.  
    2. for ($i = 0, $size = count($array); $i < $size;) {
    3.     if ($array[$i]['date_out'] >= $array[$i+1]['date_in'])  {
    4.         if ($array[$i]['date_out'] <= $array[$i+1]['date_out']) {
    5.         $array[$i]['date_out'] = $array[$i+1]['date_out'];
    6.         array_splice($array, $i+1, 1);
    7.         $i = $i+1;
    8.         }
    9.         else {
    10.         array_splice($array, $i+1, 1);
    11.         $i = $i+1;
    12.         }
    13.     }
    14.     else {
    15.     $i = $i+1;
    16.     }
    17. }
    В итоге соединяются только два соседних пересекающихся, а если пересекает третий, то он становится новым элементом конечного массива.
    Проблема известна: если элементы [0] и [1] пересекаются, срабатывает array_splice, который и удаляет элемент [1]. Элементы сдвигаются и цикл начинается с [1] и не учитывает сложившийся элемент[0].
    Вопрос: как возможно заставить цикл for работать несколько раз с одним элементом?
     
  2. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.108
    Симпатии:
    1.243
    Адрес:
    там-сям
    а зачем?

    могу предложить вариант обработки. функции добавлены исключительно для большей наглядности.
    Код (PHP):
    1. <?php
    2.  
    3. function isIntersect($a, $b)
    4. {
    5.     return ($b['date_in']  <= $a['date_out'])
    6.         && ($b['date_out'] >= $a['date_in']);
    7. }
    8.  
    9. function merge($a, $b)
    10. {
    11.     return array(
    12.         'date_in'  => min($a['date_in'],  $b['date_in']),
    13.         'date_out' => max($a['date_out'], $b['date_out'])
    14.     );
    15. }
    16.  
    17. $a = array( 
    18.   array('date_in' => 10,  'date_out' => 20),
    19.   array('date_in' => 20,  'date_out' => 40), 
    20.   array('date_in' => 30,  'date_out' => 50), 
    21.   array('date_in' => 100, 'date_out' => 200), 
    22.   array('date_in' => 110, 'date_out' => 250),
    23. );
    24.  
    25. $n = count($a);
    26. for ($i = 0; $i < $n; ++$i) {
    27.     if (!isset($a[$i])) {
    28.         continue;
    29.     }
    30.     for ($j = $i + 1; $j < $n; ++$j) {
    31.         if (isIntersect($a[$i], $a[$j])) {
    32.             $a[$i] = merge($a[$i], $a[$j]);
    33.             unset($a[$j]);
    34.         }
    35.     }
    36. }
    37.  
    38. header('Content-type: text/plain; charset=utf-8');
    39. var_export($a); 
     
  3. Ruslan

    Ruslan Активный пользователь

    С нами с:
    15 июл 2009
    Сообщения:
    13
    Симпатии:
    0
    Опробовал - работает!
    Думал, что с unset будет сложнее и решил использовать array_splice. Оказалось всё наоборот :)
    Огромное спасибо, artoodetoo!
    Тему можно закрывать.