|
ru.perl- RU.PERL ---------------------------------------------------------------------- From : vilfred 2:5020/400 10 Sep 2001 01:56:07 To : All Subject : типа сделал вывод хеша в порядке вставки, хех. гляньте, покритикуйте -------------------------------------------------------------------------------- Пните, если что не так написал, у меня проде прога работает, как описал, все исправно выводит, в порядке вставки. Идея короче примерно такая: -------------------- Без модуля Tie::IxHash вывод хеша в порядке вставки можно сделать при помощи дописывания числовой информации в хеш. Есть файл news.dat, который выводится скриптом в таком порядке, в каком данные занесены в файл. Hеобходимо удалить одновременно больше одной строчки из текста(не важно строка это, или разделитесь, это однозначно определяется переменной $/). #!/usr/bin/perl -wT use CGI 'param'; @del=param; sub del{ pop @del; $mass=~s!"|&(.*?);!!g; open F, "<news.dat" or die "Err: $!"; @mass=<F>; close F; open F, ">news.dat"; foreach $un(@mass){ $as=$un; $i++; chomp $as; $un=~s|(.*)new>(.*?)</a>(.*)\[(.*?)\]|$2$4|i; $un=~s!"|&(.*?);!!g; chomp $un; $u{"$un"}="$as#$i#\n"; } foreach $del(@del){ $del=~s!"|&(.*?);!!g; chomp $del; $terr="Link $u{$del} was deleted<p>\n" if (exists $u{"$del"}); $terr=~s!\d{8}|#(.*?)#!!ig; print $terr; $terr=""; delete $u{$del} if (exists $u{"$del"}); }{ local $_; while (($km, $_) = each %u){ push @tmp, "$u{$km}"} } @temp=grep{s/#(\d+?)#//} map{ $_ -> [1]} sort{$a->[0] <=> $b->[0]} map{[/#(\d+?)#/, $_]} grep{!$_{$_}++} @tmp; print F reverse @temp; close F; } Разъясним принцип работы скрипта. Исходная задача такова: на входе есть несколько checkbox из формы, в которых может быть поставлено больше одной галочки. Требуется найти и вычеркнуть отмеченные строчки. Файл news.dat модержит строки вида: 12345678<a href="lalalal">tra-ta- ta</a> [AAA] чекбокс отмечается текстом tra-ta-ta, т.е. что-то вида for ($i=$pos; $i<$pos+$n; $i++) { $res[$i]=~s|^(\d\d\d\d)(\d\d)(\d\d)|$3\.$2\.$1 |; print qq~<tr><td>$res[$i]</td><td> <input type=checkbox name="$1$3" value="$1$3"></td></tr>~ if($res[$i]=~m!>(.*?)</a>(.*?)\[(.*?)\]!); } т.е. name="$1$3" value="$1$3" => name=tra-ta-ta&value=tra-ta-ta. Идея заключается в том, что элементы хеша можно пронумеровать в исходном порядке вставки, который будет исходным в силу того, что хеш определяется foreach, который последовательно читает данные из массива. поэтому говорим $i++; в цикле, ставим цифру в разделителе #\d+# и получаем на выходе хеш: foreach $un(@mass){ $as=$un; $i++; chomp $as; $un=~s|(.*)new>(.*?)</a>(.*)\[(.*?)\]|$2$4|i; $un=~s!"|&(.*?);!!g; chomp $un; $u{"$un"}="$as#$i#\n"; } Дальше начинаем в хеше искать данные, которые передались через @del=param; foreach $del(@del){ $del=~s!"|&(.*?);!!g; chomp $del; $terr="Link $u{$del} was deleted<p>\n" if (exists $u{"$del"}); $terr=~s!\d{8}|#(.*?)#!!ig; print $terr; $terr=""; delete $u{$del} if (exists $u{"$del"}); } при помощи функции exists проводится проверка на наличие элемента в хеше. Итак, получили хеш с ключами, являющимися подстроками строк из файла news.dat, и значениями самих строк, т.е. в памяти точно лежит файл, превосходящий по размеру news.dat чуть меньше чем в два раза. Далее идет вытаскивание значений из файла, уже без удаленных(было сравнение по подстроке): { local $_; while (($km, $_) = each %u){ push @tmp, "$u{$km}"} } Замечательно, проверили, занесли в массив @tmp. Здесь локализация local $_; применена для того, чтобы убрать при использовании ключа -w лишнего warning из серверного лог-файла ошибок. Вытащили новый массив, который нужно соранить в файл news.dat. Теперь нужно убрать из массива @tmp повторяющиеся элементы, отсортировать по номерам #(\d+)#, убрать эти номера из элементов массива @tmp и сохранить массив в прежнем виде: @temp=grep{s/#(\d+?)#//} map{ $_ -> [1]} sort{$a->[0] <=> $b->[0]} map{[/#(\d+?)#/, $_]} grep{!$_{$_}++} @tmp; print F reverse @temp; операция grep{!$_{$_}++} удаляет из массива повторяющиеся элементы, map {[/#(\d+?)#/, $_]} создает временный список анонимных массивов, которые затем сортируются sort{$a->[0] <=> $b->[0]}, затем map{ $_ -> [1]} приводит элементы массива в удобоваримый вид и grep{s/#(\d+?)#//} вырезает нуумерацию массива, оставшуюся от начального формирования хеша %u. Далее оборачиваем конечный массив @temp функцией reverse и получам такой-же файл news.dat, только без элементов, отмеченных пользователем в чекбоксе. Дима -- TEAM [Маньяки] Отправлено через сервер Talk.Ru - http://www.talk.ru --- ifmail v.2.15dev5 * Origin: Talk.ru (2:5020/400) Вернуться к списку тем, сортированных по: возрастание даты уменьшение даты тема автор
Архивное /ru.perl/64880235aa8f.html, оценка из 5, голосов 10
|