parser

Написать ответ на текущее сообщение

 

 
   команды управления поиском

Ответ

Misha v.3 23.08.2011 16:54 / 24.08.2011 07:24

быстренько набросал свой вариант оператора rsplit (подробно не тестировал. структура результирующей таблицы изменилась).

вот сравнение (rsplit0 -- реализация Eugene-а, rsplit1 -- моя). можно сделать copy/paste и посмотреть самостоятельно. для измерения используется Erusage.p:
@main[]
$cnt(9999)
$t[^table::create{text	regex	options	method	col	res	check
12:01. 14:05, 18:00,21:20 Спортивные новости	[,\.]\s?		rsplit0	piece	12:01 14:05 18:00 21:20 Спортивные новости	0	warming up

12:01. 14:05, 18:00,21:20 Спортивные новости	[,\.]\s?		rsplit0	piece	12:01 14:05 18:00 21:20 Спортивные новости	1
2004-12-22 13:30	[^^0-9]	r	rsplit0	piece	30 13 22 12 2004	1
2004/12//22	/{1,2}	r	rsplit0	piece	22 12 2004	1
1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30	/	l	rsplit0	piece	1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30	1

12:01. 14:05, 18:00,21:20 Спортивные новости	[,\.]\s?		rsplit1	1	12:01 14:05 18:00 21:20 Спортивные новости	1
2004-12-22 13:30	[^^0-9]	r	rsplit1	1	30 13 22 12 2004	1
2004/12//22	/{1,2}	r	rsplit1	1	22 12 2004	1
1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30	/	l	rsplit1	1	1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30	1
}]


^memory:compact[]

^t.menu{
	^do[$t.text;$t.regex;$t.options;$t.method;$t.col;$t.res;$t.check]
	^memory:compact[]
}



@do[text;regex;options;method;column;valid;doCheck][m;i;parts;v]
$m[$$method]
^Erusage:measure{^for[i](0;$cnt){$parts[^m[$text;$regex;$options]]}}[v]
^if($doCheck){
	<hr />
	^check[$text;^parts.menu{$parts.$column}[ ];$valid]
	Time: $v.time ms<br />
	KB: $v.memory_kb
}




@check[text;res;valid]
$text => $res -- ^if($res eq $valid){OK}{<b>FAIL</b>}<br />



@rsplit0[text;regex;delimiter][table_split]
^if(def $text && def $regex){
	$table_split[^table::create{piece}]
	$result[^text.match[(.*?)(?:$regex)][g]{^if(def $match.1){^table_split.append{$match.1}}}]
	^if(def $result){^table_split.append{$result}}
	^if(!def $delimiter){$delimiter[lv]}
	^switch[^delimiter.lower[]]{
		^case[r;rv;vr]{$result[^table::create[$table_split;$.reverse(1)]]}
		^case[rh;hr]{$result[^table::create[$table_split;$.reverse(1)]]$result[^result.flip[]]}
		^case[h;lh;hl]{$result[^table_split.flip[]]}
		^case[DEFAULT]{$result[$table_split]}
	}
}{
	^throw[parser.runtime;rsplit;parameters ^$text and ^$regex must be defined]
}


@rsplit1[text;regex;delimiter][table_split]
^if(def $text && def $regex){
	$result[^text.match[(.+?)(?:$regex|^$)][g]]
}{
	$result[^table::create[nameless]{}]
}
^if($result && def $delimiter){
	^if(^delimiter.pos[r]>=0 || ^delimiter.pos[R]>=0){
		$result[^table::create[$result;$.reverse(true)]]
	}
	^if(^delimiter.pos[v]>=0 || ^delimiter.pos[V]>=0){
		$result[^result.flip[]]
	}
}
у меня на компе результаты такие:
 12:01. 14:05, 18:00,21:20 Спортивные новости => 12:01 14:05 18:00 21:20 Спортивные новости -- OK
 Time: 205.004 ms
 KB: 14616 

 2004-12-22 13:30 => 30 13 22 12 2004 -- OK
 Time: 210.003 ms
 KB: 16512 

 2004/12//22 => 22 12 2004 -- OK
 Time: 165.002 ms
 KB: 12404 

 1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30 => 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 -- OK
 Time: 720.012 ms
 KB: 64264 

 12:01. 14:05, 18:00,21:20 Спортивные новости => 12:01 14:05 18:00 21:20 Спортивные новости -- OK
 Time: 100.001 ms
 KB: 3812 

 2004-12-22 13:30 => 30 13 22 12 2004 -- OK
 Time: 115.002 ms
 KB: 5696 

 2004/12//22 => 22 12 2004 -- OK
 Time: 105.002 ms
 KB: 5452 

 1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24/25/26/27/28/29/30 => 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 -- OK
 Time: 220.003 ms
 KB: 22460
т.е. новый rsplit1 работает в ~2 раза быстрее, использует в ~2 раза меньше памяти и занимает в 1.7 раза меньше байтиков :)

при обработке больших строк (когда в результирующей таблице будет много записей) результат ещё лучше в пользу rsplit1 (четвёртый тест).

P.S. по хорошему надо ещё приделать проверку на тип $regex (string/regexp)