[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: пропускать только буквы Aa-Zz и Аа-Яя
artlayers
Как сделать средствами php так чтобы текстовая переменная, содержащая в себе некоторую строку, ну например "asdfaklwjnwkwqJGBSASA121SA GCFSA - dsfdsdd" проверялась на наличие в ней только символов Aa-Zz и Аа-Яя и знаков _ - — и пробела. Если присутвует хотя бы один символ не из этой последовательности, то нужно об этом просто сказать. Реализацию через strpos знаю, но она слишком глупа нужно поумнее. Подскажите пожалуйста.



Спустя 5 минут, 49 секунд (19.06.2010 - 09:47) tomash написал(а):

Спустя 31 секунда (19.06.2010 - 09:48) Bezdna написал(а):
Цитата (artlayers @ 19.06.2010 - 09:41)
Реализацию через strpos знаю, но она слишком глупа нужно поумнее


Осмелюсь предложить preg_match(). Надеюсь не самая глупая функция?

Спустя 7 минут, 34 секунды (19.06.2010 - 09:55) artlayers написал(а):
Мне еще важна скорость. Вопрос preg_match() будет ли быстрее чем strpos работать?

Спустя 2 минуты, 25 секунд (19.06.2010 - 09:58) tomash написал(а):
artlayers
Смотря как использовать, регулярные выражения вещь мощная, но требующая ресуров!

Спустя 4 минуты, 46 секунд (19.06.2010 - 10:02) artlayers написал(а):
а через strpos можно как-то задать разом проверялось наличие только букв, при этом не прописывая if(strpos($str,"A"))&&(strpos($str,"a"))... то есть для каждой буквы?

Спустя 1 минута, 11 секунд (19.06.2010 - 10:03) Basili4 написал(а):
Регулярки более медленные из своей мощности

Спустя 6 минут, 37 секунд (19.06.2010 - 10:10) tomash написал(а):
artlayers
Нет, по моему нельзя

Спустя 1 минута, 34 секунды (19.06.2010 - 10:12) DedMorozzz написал(а):
Цитата
Смотря как использовать
Как не используй - будет намного медленее

Спустя 3 минуты, 49 секунд (19.06.2010 - 10:15) tomash написал(а):
DedMorozzz
Если использовать в цикле с условиями или в таком виде
if(strpos($str,"A"))&&(strpos($str,"a"))
для каждой буквы??

Спустя 28 минут, 26 секунд (19.06.2010 - 10:44) DedMorozzz написал(а):
В рамках разумного. И не факт, что даже в цикле будет медленее:
Цитата
раз
$result_txt = preg_replace("# программ(.+?) #is", " <b>программ\\1</b> ", $txt);

два
$txt = " ".$txt." ";
$txtl = strtolower($txt);
$len = strlen($txtl);
$start = array();
$finish = array();
for($i=0;$i<$len;$i++)
{
if( substr($txtl,$i,9) == " программ" )
{
  $start[$i] = $i;
  $pos = $i+9;
  while( substr($txtl,$pos,1) != " " and $pos <= $len )$pos++;
  if($pos < $len)$finish[$i] = $pos;
  else unset($start[$i]);
}
}

$result_txt = "";
for($i=0;$i<$len;$i++)
{
if( in_array($i,$start) )$result_txt .= "<b>";
$result_txt .= substr($txt,$i,1);
if( in_array($i,$finish) )$result_txt .= "</b>";
}
$result_txt = substr($result_txt,1,-1);

Эти две функции делают одно и то же: поиск и выделение целого слова по началу.
Первая выглядит элегантней. Но кинь текст мегабайт на 10 с сотнями или тысячами вхождений заданного слова, и ты подвесишь сервер на пару минут; вторая функция отстреляется буквально за секунду.

Спустя 10 минут, 30 секунд (19.06.2010 - 10:54) tomash написал(а):
DedMorozzz
Не по теме. на все 100% согласен, что если можно обойтись без регулярки, то лучше все сделать строковыми ф-ми. Естественно в рамках разумного.

Спустя 6 часов, 7 минут, 18 секунд (19.06.2010 - 17:02) gzim9x написал(а):
DedMorozzz

не сходится...

первый вариант уделывает 2 в несколько десятков раз (php 5.3.2), причем в качестве первого можно использовать и более быстрый аналог (~30%):


preg_replace("/ (программ[^ ]+)/is", " <b>\\1</b>", $txt);


Возможно это из-за utf -- потому как второй вариант без допиливания с utf работать не будет -- для сравнения придется заменять на что-то подобное mb_substr($txtl,$i,9,'UTF-8')...


Спустя 2 часа, 12 минут, 54 секунды (19.06.2010 - 19:15) artlayers написал(а):
Сделал в общем вот так
preg_match('#^[—\а-яa-z_\-+ ]+$#i', $id)

Но появилась проблема:
для латиницы все хорошо, а для кириллицы вот такое, например слово "кириллица" выглядит как "%EA%E8%F0%E8%EB%EB%E8%F6%E0" что можно тут придумать, чтобы такую строку проверить?

Спустя 16 минут, 34 секунды (19.06.2010 - 19:31) Ice написал(а):
url_decode() ?

Спустя 10 минут (19.06.2010 - 19:41) DedMorozzz написал(а):
Цитата
первый вариант уделывает 2 в несколько десятков раз (php 5.3.2)

Что кидал? Сколько тыс вхождений и каков объём проверочного текста был?

Спустя 55 минут, 34 секунды (19.06.2010 - 20:37) artlayers написал(а):
помогло, благодарю.

Спустя 44 минуты (19.06.2010 - 21:21) gzim9x написал(а):
Цитата
Что кидал? Сколько тыс вхождений и каков объём проверочного текста был?


проверялось порядка 400 тыс вхождений
если нужно -- приведу код проверок -- но думаю что на этой функции не стоит сравнивать быстродействие регулярок (preg_match, preg_replace) и str_pos и str_replace -- все-таки оптимизировать там есть что.
На практике код с простыми регулярки как правило отстает на 10-15% (что называется из пушки по воробьям), но если проверки "суровые" то выигрывают.



Спустя 1 час, 39 минут, 31 секунда (19.06.2010 - 23:00) DedMorozzz написал(а):
Никогда не задавался вопросом: "какая разница в процентах". А насчёт оптимизации - то этот вопрос не ко мне smile.gif Ибо видно, что сие цитата. Пруф - http://phpforum.ru/index.php?showtopic=15291&st=15 . Но учитывая, что это писал FatCat, сомневаюсь, что не проверенный вариант кидал. Организую на досуге тест.
Но я и так прекрасно понимаю, что регулярка проиграет. Хотя бы по тому, что парсеры (поиск нужного контента регуляркой) работает по 10 сек у мну. Строковые ф-и всё делают в момент....в общем кинь свой тест, интересно таки.

Спустя 2 часа, 46 минут, 2 секунды (20.06.2010 - 01:46) gzim9x написал(а):
DedMorozzz

Ok -- вот результаты тестов
массив из 1000 слов в которых однозначно есть вхождения -- желающие могут увеличить длину строки wink.gif


<?php
// формируем строку с вхождениями
$a = array ('программист', 'программирование', 'пишет', 'программы', 'код', 'emacs', 'phpforum');
$txt='';
for ($i=1,$l=sizeof($a);$i<1000;$i++)
$txt.=' '.$a[rand(0,$l-1)];

// вариант с регуляркой
$time1 = microtime(true);
$result_txt = preg_replace("# программ(.+?) #is", " <b>программ\\1</b> ", $txt);
$time2 = microtime(true) - $time1;

print $time2."\n";

// вариант с "ускоренной" регуляркой
$time1 = microtime(true);
$result_txt = preg_replace("/ (программ[^ ]+)/is", " <b>\\1</p>", $txt);
$time2 = microtime(true) - $time1;

print $time2."\n";

// вариант с str_.....
// дадим этому варианту фору из-за кривой реализации utf в PHP

$txt = iconv("utf-8", "windows-1251"," ".$txt." ");
$t= iconv("utf-8", "windows-1251"," программ");

$time1 = microtime(true);

$txtl = strtolower($txt);
$len = strlen($txtl);
$start = array();
$finish = array();
for($i=0;$i<$len;$i++)
{

if( substr($txtl,$i,9) == $t )
{

$start[$i] = $i;
$pos = $i+9;
while( substr($txtl,$pos,1) != " " and $pos <= $len )$pos++;
if($pos < $len)$finish[$i] = $pos;
else unset($start[$i]);
}
}

$result_txt = "";
for($i=0;$i<$len;$i++)
{
if( in_array($i,$start) )$result_txt .= "<b>";
$result_txt .= substr($txt,$i,1);
if( in_array($i,$finish) )$result_txt .= "</b>";
}
$time2 = microtime(true) - $time1;

$result_txt = iconv("windows-1251", "utf-8",substr($result_txt,1,-1)); // еще немного форы wink.gif

print $time2."\n";

?>

Результаты:
0.0013260841369629
0.001086950302124
0.95612096786499



я не претендую на то что регулярки быстрее -- просто в них меньше места для "человеческого фактора". В данном случае можно запросто оптимизировать 3 вариант, но.... такой задачи не было wink.gif

Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.