Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Perl: Общие вопросы > Поиск в хеше с его преобразованием? |
Автор: Suppir 21.4.2010, 08:21 |
Есть хеш %all вида: 12 3 = 1 12 4 = 1 1245 = 1 1236 = 1 123 6 8 89 =1 ... Есть строка $a="1 2 3"; Как сделать функцию, которая будет проверять наличие строки $a в хеше %all, не учитывая пробелы в строке и хеше? Однако значения в хеше нельзя менять навсегда, так как он дальше используется с этими пробелами. Проблема в том, что хеш очень большой и строки в нем длинные. Необходимо оптимизировать поиск. |
Автор: dva300 21.4.2010, 12:57 | ||||
хм....
|
Автор: amg 21.4.2010, 15:05 | ||
|
Автор: Suppir 23.4.2010, 09:23 |
amg ближе всех оказался к истине! |
Автор: amg 23.4.2010, 09:33 |
А в чем же настоящая истина? ![]() |
Автор: odmink0 23.4.2010, 11:00 | ||
Хочу заметить, что решение amg находит даже те ключи хеша, которые не равны строке $a (с условием, что из неё и из ключа уберут пробелы), а содержат эту строку. То есть если $a='123', то найдутся и ключи, равные '12345' и '555123555'. Чтобы обеспечить равенство, можно использовать:
Кроме того не вижу смысла использовать each(), когда можно использовать keys() - раз уж мы все равно ведём поиск только среди ключей. |
Автор: amg 23.4.2010, 12:04 |
keys создаст дополнительный массив из ключей хэша, а это лишний расход и памяти, и времени. |
Автор: NuINu 24.4.2010, 12:42 |
какая глупость, хеш для того и создаеться что бы осуществлять быстрый доступ к элементам по индексу, а вы не пойми что из него сделали. нужно просто изменить структуру хеша, и тогда все будет находиться по простому exist |
Автор: amg 24.4.2010, 12:58 |
А Вы предложите умное решение, а то рекомендация "просто изменить структуру хеша" не очень информативна ![]() |
Автор: amg 26.4.2010, 07:51 | ||
Господа! Ну почему вам так не нравится функция each? ^ ![]() Еще раз процитирую кусочек самого первого поста:
Сейчас потестировал на хэше из 2_500_000 элементов с длиной ключей 70 символов. Функция KSURi на моем компьютере работает 11 с и скрипт требует 630 М памяти. Если в этой функции просто заменить for my $k ( keys %$hash ) { на while ( (my $k) = each %$hash ) { то будет 9 с и 350 М. Выигрыш по времени действительно невелик, но по памяти существенен. Я, может неправильно, понял топикстартера так, что нужно искать не совпадение строки с ключом (без пробелов), а наличие подстроки в ключе. Пэтому постарался сделать так, чтобы в цикле было только одно регулярное выражение (видимо, подготовительные операции для этого публика и приняла за выпендреж). Чтобы определять наличие подстроки в функции KSURi, туда нужно внести еще одно регулярное выражение, т.е. $str eq $k заменить на $k =~ /$str/, а это даст еще лишние 2 с. Кстати, KSURi, судя по прибавке памяти, получается (перл 5.8), что keys создает все же массив ключей, а не массив ссылок на них. Хотя в данной ситуации ( for (keys %hash) ), казалось бы, можно было ограничиться массивом ссылок. Может, в более новых перлах так? |
Автор: Suppir 26.4.2010, 11:59 |
Ребята, я сделал эту функцию без хеша. Просто перебором по двум массивам и сравнением измененных элементов этих массивов. Вариант с хешем отбирал очень много оперативки. |
Автор: NuINu 26.4.2010, 14:13 | ||||
элементарно
|
Автор: amg 26.4.2010, 14:52 |
Как выяснилось, даже один хэш не влазит в память, а Вы предлагаете завести еще один такой же. ![]() Но Вы безусловно правы в том, что нужно было с самого начала менять подход к решению задачи... Тут упрек топикстартеру: прежде чем просить о помощи, нужно было подумать, ведь потребляемую хэшем память можно http://forum.vingrad.ru/forum/topic-219798/anchor-entry1575015/15.html. |
Автор: Suppir 27.4.2010, 08:14 |
Я знал, что хеш много памяти кушает, но не предполагал, что настолько ![]() |
Автор: mvsgt 27.4.2010, 16:27 |
когда хэш начинает кушать память, надо использовать Berkeley DB , например DB_File . Некоторое замедление, конечно, будет, но память освободится. Может быть, фрагмент $a = join '', split '\s*', $a; лучше заменить на $a =~ s/\s+//go; |
Автор: NuINu 27.4.2010, 19:52 |
наверное лучше ![]() так же согласен на счет базы, а так же можно увеличить память. кстати первый массив можно и не оформлять в виде хеша. как я понял он достаточно бестолковый. у меня нет данных на 2 000 000 строк, а генерить лень. |
Автор: amg 28.4.2010, 05:11 |
perl -lne "print rand for 1..2e6" > big_file ![]() |
Автор: NuINu 28.4.2010, 14:29 |
я не уверен что это будут те самые данные с пробелами |
Автор: amg 28.4.2010, 15:30 |
Я бы даже сказал, что почти наверняка пробелов там не будет ![]() |