Тема
|
Match - може ли да се оптимизира
|
|
Автор |
bira_more (бира) |
Публикувано | 20.07.07 23:35 |
|
Имам променлива $keep (една буква)
Имам променлива $buf
Целта е да разбера дали $buf се състои само от $keep
Кода по долу - върши работа.
Опитах няколко неща с match ама нещо не мога да получа каквото искам.
@all=split(//,$buf);
$L=@all;
for($j=0;$j<$L;$j++){
$p=$all[$j];
if($p!=$keep){
$Same=0;
last;
}
}
Например
if($buf =~m/$keep{length($buf)}/)
Не работи - поне не така както бих искал аз.
Bеer? Mоre?
|
|
Тема
|
Re: Match - може ли да се оптимизира
[re: bira_more]
|
|
Автор | errata (Нерегистриран) |
Публикувано | 24.07.07 07:21 |
|
To i az sum edin pishman programist, no sled kato vsichki specove sa otishli na more ...
Ta znachi, ako $keep e bukva (t.e. string s dulzhina 1), kakvo ti prechi da izpolzvash operatora eq (za sravniavane na strings) ili zadulzhitelno triabva da e s match?
if ($buf eq $keep) {...}
|
|
Тема
|
Re: Match - може ли да се оптимизира
[re: bira_more]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 24.07.07 12:31 |
|
нещо от сорта би следвало да е поне толкова ефективно колкото и "eq".
use strict;
my @ar1 = qw(a a a);
my @ar2 = qw(a a b);
my $buf = 'a';
print "Array 'ar1' contains only '$buf' chars\n" if _eqls(\@ar1, $buf);
print "Array 'ar2' contains only '$buf' chars\n" if _eqls(\@ar2, $buf);
sub _eqls {
my $arr = shift;
my $buf = shift;
my $h = {};
for my $el (@$arr) {
$h->{$el}++;
last if keys %$h > 1;
}
return 'true' if $h->{$arr->[0]} == scalar @$arr;
return undef;
}
|
|
Тема
|
Re: Match - може ли да се оптимизира
[re: bira_more]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 24.07.07 12:43 |
|
или защо не компилиран регулярен израз?
my $buf = 'a';
my $keep = 'aaa';
my $regex = qr{^\Q$buf\E+$};
$keep =~ /$regex/;
|
|
|
$keep="8";
$buf="8889";
$buf1="8888888";
няма поне според мен нещо което директно да казва
$keep == $buf1;
$keep != $buf;
Bеer? Mоre?
|
|
|
Мерси много - точно това търсех.
Сега ще огледам какво прави с надеждата и да разбера повече за Perl / regexp
Някой ден ако се видим - имаш ена бира :)
Bеer? Mоre?
|
|
|
if($keep =~ /^$buf+$/)
е достатъчно.
Много мерси за идеята - така де принтнах $regex да видя какво става :)
Bеer? Mоre?
|
|
Тема
|
Re: В същност
[re: bira_more]
|
|
Автор | novobranec (Нерегистриран) |
Публикувано | 24.07.07 21:01 |
|
Ако ти трябва за това което си мисля (мачване на префикси) ще береш ядове, този regex не е достатъчен.
|
|
|
Ще го обясня на C че ми е по лесно.
Имам
char S[x];
char C;
ако всички букви на S са равни на C Same=1
else Same = 0;
Пример
S="88888888888";
C='8';
Same = 1;
S="888898888888";
C='8';
Same = 0;
Bеer? Mоre?
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 25.07.07 10:52 |
|
novobranec, нищо лошо няма да се разчита на толкова добре оптимизирана машина като тази за регулярните изрази в Perl. Пример с 'eq' и regex:
use strict;
use Benchmark qw(:all);
$main::string = 'aaaaaaaaaa';
$main::buffer = 'a';
@main::array = split '', $main::string;
#my $results =
timethese(10_000_000, {
'equal' => '$main::buffer eq $_ or last for @main::array',
'regex' => '$main::string =~ /^\Q$main::buffer\E+$/o',
});
#cmpthese( $results );
__END__
output:
Benchmark: timing 10000000 iterations of equal, regex...
equal: 31 wallclock secs (27.16 usr + 0.01 sys = 27.17 CPU) @ 368053.00/s (n=10000000)
regex: 7 wallclock secs ( 7.23 usr + 0.00 sys = 7.23 CPU) @ 1383125.86/s (n=10000000)
|
|
Тема
|
Re: Yes
[re: bira_more]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 25.07.07 11:04 |
|
за нищо, тва ми е работата, поне беше.
но по-добре "компилиран" регулярян израз ако ще се ползва многократно, цитат от `perl perlrequick`:
There are a few more things you might want to know about matching operators. In the code
$pattern = 'Seuss';
while (<>) {
print if /$pattern/;
}
perl has to re-evaluate $pattern each time through the loop. If $pattern won't be changing, use the "//o" modifier, to only perform variable substitutions once.
колкото до бирата, добре че ме подсети, да видя колко е изстудена, че да почвам "отрудения" ден
|
|
Тема
|
Re: В същност
[re: perlmonk]
|
|
Автор | novobranec (Нерегистриран) |
Публикувано | 25.07.07 13:45 |
|
Изобщо спор няма, просто имах предвид че няма да му свърши работа дадения regex.
|
|
Тема
|
Re: В същност
[re: bira_more]
|
|
Автор | novobranec (Нерегистриран) |
Публикувано | 25.07.07 13:53 |
|
Аз нещата ги виждам така:
$same=1;
for (0..length($buf)){
if (substr($buf,$_,1) ne $keep){
$same=0;
last;
}
}
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 25.07.07 14:04 |
|
според мен точно този регулярен е това, което трябва. дори да допуснем, че имаш "бързо напускане" (last), пак е по-бавно от регулярната машина:
#!/usr/bin/perl
use strict;
use Benchmark qw(:all);
$main::string = 'aaaaaaaaaa';
$main::buffer = 'a';
@main::array_full = split '', $main::string;
@main::array_part = qw(a b a a a a a a a a);
my $result = timethese(10_000_000, {
'equal_full' => '$main::buffer eq $_ or last for @main::array_full;',
'equal_part' => '$main::buffer eq $_ or last for @main::array_part;',
'regex' => '$main::string =~ /^\Q$main::buffer\E+$/o',
});
cmpthese( $result );
__END__
stdout:
Benchmark: timing 10000000 iterations of equal_full, equal_part, regex...
equal_full: 58 wallclock secs (28.92 usr + 0.13 sys = 29.05 CPU) @ 344234.08/s (n=10000000)
equal_part: 11 wallclock secs ( 8.98 usr + 0.00 sys = 8.98 CPU) @ 1113585.75/s (n=10000000)
regex: 9 wallclock secs ( 8.05 usr + -0.01 sys = 8.04 CPU) @ 1243781.09/s (n=10000000)
Rate equal_full equal_part regex
equal_full 344234/s -- -69% -72%
equal_part 1113586/s 223% -- -10%
regex 1243781/s 261% 12% --
а може би не съм разбрал условието?
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 25.07.07 14:14 |
|
това е най-бавния вариант:
#!/usr/bin/perl
use strict;
use Benchmark qw(:all);
$main::string = 'aaaaaaaaaa';
$main::buffer = 'a';
$main::same = 1;
@main::array_full = split '', $main::string;
@main::array_part = qw(a b a a a a a a a a);
my $result = timethese(10_000_000, {
'equal_full' => '$main::buffer eq $_ or last for @main::array_full;',
'equal_part' => '$main::buffer eq $_ or last for @main::array_part;',
'regex' => '$main::string =~ /^\Q$main::buffer\E+$/o',
'substr' => 'for (0..length($main::string)) {
if (substr($main::string,$_,1) ne $main::buffer) {
$main::same=0;
last;
}
}',
});
cmpthese( $result );
__END__
stdout:
Benchmark: timing 10000000 iterations of equal_full, equal_part, regex, substr...
equal_full: 38 wallclock secs (30.03 usr + 0.04 sys = 30.07 CPU) @ 332557.37/s (n=10000000)
equal_part: 13 wallclock secs ( 8.79 usr + 0.00 sys = 8.79 CPU) @ 1137656.43/s (n=10000000)
regex: 9 wallclock secs ( 7.81 usr + 0.01 sys = 7.82 CPU) @ 1278772.38/s (n=10000000)
substr: 72 wallclock secs (51.92 usr + 0.05 sys = 51.97 CPU) @ 192418.70/s (n=10000000)
Rate substr equal_full equal_part regex
substr 192419/s -- -42% -83% -85%
equal_full 332557/s 73% -- -71% -74%
equal_part 1137656/s 491% 242% -- -11%
regex 1278772/s 565% 285% 12% --
|
|
Тема
|
Re: В същност
[re: perlmonk]
|
|
Автор | novobranec (Нерегистриран) |
Публикувано | 25.07.07 16:05 |
|
Пропускаш нещо, не си включил split-a в бенчмарка...
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 25.07.07 16:14 |
|
да, няма и смисъл да го слагам в benchmark.
това е 1-нократна операция и не подлежи на тестове за performance.
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 25.07.07 16:28 |
|
дори и да включа split при образуването на масива, с който се тества, какво от това??? не защитавам теорията с употребата на масив, а оборвам твоята, която е в пъти по-бавна от регулярния тест:
my $result = timethese(5_000_000, {
'equal_full' => '@main::array_full = split //, $main::string; $main::buffer eq $_ or last for @main::array_full;',
'equal_part' => '@main::array_part = qw(a b a a a a a a a a); $main::buffer eq $_ or last for @main::array_part;',
'regex' => '$main::string =~ /^\Q$main::buffer\E+$/o',
'substr' => 'for (0..length($main::string)) {
if (substr($main::string,$_,1) ne $main::buffer) {
$main::same=0;
last;
}
}',
});
__END__
stdout:
Benchmark: timing 5000000 iterations of equal_full, equal_part, regex, substr...
equal_full: 46 wallclock secs (39.19 usr + 0.00 sys = 39.19 CPU) @ 127583.57/s (n=5000000)
equal_part: 23 wallclock secs (21.37 usr + 0.00 sys = 21.37 CPU) @ 233972.86/s (n=5000000)
regex: 5 wallclock secs ( 3.74 usr + 0.00 sys = 3.74 CPU) @ 1336898.40/s (n=5000000)
substr: 24 wallclock secs (22.01 usr + 0.00 sys = 22.01 CPU) @ 227169.47/s (n=5000000)
Rate equal_full substr equal_part regex
equal_full 127584/s -- -44% -45% -90%
substr 227169/s 78% -- -3% -83%
equal_part 233973/s 83% 3% -- -82%
regex 1336898/s 948% 489% 471% --
|
|
Тема
|
Re: В същност
[re: perlmonk]
|
|
Автор | novobranec (Нерегистриран) |
Публикувано | 25.07.07 20:50 |
|
OK, никой не оспорва че е с regex е по-бързо, но през цялото време сравняваш процедура която проверява дали в дадения стринг се съдържа 'само' дадения char, с regex който проверява дали изобщо се съдържа дадения char в дадения string...
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | novobranec (Нерегистриран) |
Публикувано | 25.07.07 20:56 |
|
Ooops, съжалявам нещо много бавно мисля в тая жега...
perlmonk, абсолютно си прав в ситуацията, не чети предишния ми пост
Нещо май скука ни гони тез дни, глей къв флейм заформихме...
|
|
|
Мисля че си го разбрал
Точно regex върши работа идеално.
Става въпрос за Asterisk (софтуерна телефонна централа). Той има AGI* - a AGI може да е Perl или каквото поискаш там (PHP, Python, Ruby, C приложения).
Та юзъра набива някакви DTMF и ако DTMFите са еднакви - правя едно, ако са различни - друго.
Първия DTMF ми е buffer, а останалите ги събирам в string.
Съответно в string може да има само цифри и * и #, ама за * и # правя предварителна проверка, та може да има само цифри
_______
AGI - Asterisk Gateway Interface
Bеer? Mоre?
|
|
Тема
|
Re: В същност
[re: novobranec]
|
|
Автор | perlmonk (Нерегистриран) |
Публикувано | 26.07.07 12:28 |
|
карай, много "важно", нали за flames са тея клубове
|
|