Отпарсить даты и выполнить сортировку

sl1p

Новичок
Есть такая оригинальная задачка.. Не уверен что здесь следует использовать рег.выр., но другое не приходит в голову..

Есть текст такого вида:
29/05/2007р.
fdfdfd

15/10/2007р.
dfcvvcvc

15/10/2007р.
vcvcvcvc

15/10/2007р.
eveve


15/10/2007р.
vev4

16/10/2007р.
vevervre

16/10/2007р.
vrevev


24/10/2008р.
vrevrevre

24/10/2008р.
vrev4


24/10/2008р.
verv4


24/10/2008р.
verve

24/10/2008р.
verve

08/10/2010р.
vreveveer

08/10/2010р.
erverve

8/10/2010р.
verveveev

08/10/2010р.
verver
11/12/2008р.
vevre
Нужно его распарсить по блокам (где блок это текст от даты, до конца даты или до конца строки)
Далее по дате отсортировать ASC/DESC, неважно, главное по порядку.
И в конце концов слепить текст обратно. Он должен иметь точно такой же вид как показано выше, но отсортированным.

Основная просьба помочь составить рег.выр., чтобы на выходе был массив подобный:

PHP:
array( 
    array( 
        0 => date, 
        1 => text 
    ), 
    ..... 
)
 

sl1p

Новичок
Вроде получилось. Посмотрите пожалуйста, не через жопу ли:)

PHP:
			function _sortdate_turntonormal( $date ) {
				$date = preg_replace('#[^(\d{2}/\d{2}/\d{4})]#', '', $date);
				$date = explode('/', $date);
				$date = array_reverse($date);
				$date = implode('-', $date);
				return $date;
			}
			function _sortdate_( &$a, &$b ) {
				global $filter_order_Dir;
				
				$aa = _sortdate_turntonormal($a[0]);
				$bb = _sortdate_turntonormal($b[0]);
				switch($filter_order_Dir) {
					case 'asc':
						return $aa > $bb? -1 : 1;
						break;
					case 'desc':
					default:
						return $aa < $bb? -1 : 1;
						break;
				}
			}
				$out = preg_split('#(\d{2}/\d{2}/\d{4}р.)#', $row->text, 0, PREG_SPLIT_DELIM_CAPTURE);
				$tosort = array();
				for($i = 1, $l = count($out); $i < $l; $i+=2) {
					$tosort[] = array(
						$out[$i],
						$out[$i+1]
					);
				}
					
				usort($tosort, '_sortdate_');
					
				$text = array();
				for($i = 0, $l = count($tosort); $i < $l; $i++) {
					$text[] = $tosort[$i][0]."\n".$tosort[$i][1];
				}
				$text = implode('<hr>', $text);
 

Вурдалак

Продвинутый новичок
Достаточно preg_match_all() с PREG_SET_ORDER и usort(). Код будет намного короче.
 

Вурдалак

Продвинутый новичок
PHP:
function cmpMatchesAsc($a, $b)
{
    return strcmp($a[3] . $a[2] . $a[1], $b[3] . $b[2] . $b[1]);
}

function cmpMatchesDesc($a, $b)
{
    return -cmpMatchesAsc($a, $b);
}

preg_match_all('#(\\d{2})/(\\d{2})/(\\d{4})р.\r?\n(.*)#', $s, $matches, PREG_SET_ORDER);

$filter_order_Dir = 'asc';

if( $filter_order_Dir == 'asc' ) {
    $callback = 'cmpMatchesAsc';
} else {
    $callback = 'cmpMatchesDesc';
}

usort($matches, $callback);

$out = '';

foreach($matches as $match) {
    $out .= $match[0] . "\n\n";
}

echo nl2br(htmlspecialchars($out));
 

sl1p

Новичок
Не покатило немного выражение, вы наверное не заметили, но в первом посте было указано, что блок текста это текст от даты и до её конца, либо до конца строки, т.е. текст после даты может быть не с одним переносом строки.. так что привязаться можно только к дате или к концу строки.
+ там разные вариации даты могут быть как оказалось.. +разные делимы даты..

вобщем всё равно остановился на сплите, если возможно то помогите переделать под preg_match_all()

PHP:
$out = preg_split("#(\d{2})(?:/|\.)(\d{2})(?:/|\.)(\d{2,4})(?:р\.)?#is", $row->text, 0, PREG_SPLIT_DELIM_CAPTURE);
И спасибо за попытку помочь.
 

Вурдалак

Продвинутый новичок
Что значит «текст от даты до её конца»? В этом нет вообще никакого смысла.
 

Вурдалак

Продвинутый новичок
Тогда непонятно где ещё идёт текст, а где уже идёт следующая дата. Т.е. почему ты выделил текст так:
08/10/2010р.
вавававав
ававава
ававав

08/10/2010р.
erverve
а не так:
08/10/2010р.
вавававав
ававава
ававав
08/10/2010р.
erverve
?
 

sl1p

Новичок
ну как текст это то что между 2мя датами..

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

08/10/2010р.
первый блок
08/10/2010р.
второй блок
 
Сверху