Анимация
JavaScript


Главная  Библионтека 

0 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 [ 119 ] 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

for my Smsg (sort {

Sa->{SUBJECT} cmp $b->{SUBJECT}

Sa->{NUMBER} <=> $b->{NUMBER} } emsgs

print $msg->{TEXT}:

Работая с полноценными хэшами, нетрудно добавить дополнительные критерии сортировки. Почтовые ящики часто сортируются сначала по теме, а затем по дате сообщения. Основные трудности связаны с анализом и сравнением дат. Модуль Date::Manip помогает справиться с ними и возвращает строку, которую можно сравнивать с другими. Тем не менее программа datesort из примера 10.4, исполь-

Если функции sort передается список (0,1,2,3), после сортировки будет получена некоторая перестановка - например, (2,1,3,0). Мы перебираем элементы списка в цикле for и выводим каждое сообщение.

В примере 10.2 показано, как бы написал эту программу программист с большим опытом работы на awk. Ключ -00 используется для чтения абзацев вместо строк.

Пример 10.2. bysub2

#!/usr/bin/perl -пОО

# bysub2 - сортировка по темам в стиле awk BEGIN { Smsgno = -1 }

$sub[++$msgno] = (/"Subject;\s*(?;Re;\s*)*( *)/mi)[0] if /From/m; $msg[$msgno] .= $ ;

END { print msg[ sort { $sub[$a] cmp $sub[$b] $a <=> $b } (0 . . $#msg) ] }

Параллельные массивы широко использовались лишь на ранней стадии существования Perl. Более элегантное решение состоит в том, чтобы сохранять сообщения в хэше. Анонимный хэш (см. главу 11) сортируется но каждому нолю.

Программа из примера 10.3 построена на тех же принципах, что и примеры 10.1 и 10.2.

Пример 10.3. bysubS

#!/usr/bin/perl -00

# bysubS - sort by subject using hash records use strict;

my gimsgs = (); while (<>) {

push emsgs, {

SUBJECT => /"Sub]ect;\s.(?;Re;\s*).(. 0/mi, NUMBER => scalar gmsgs, Я Номер сообщения TEXT => , ) if /"From/m; $msgs[-1]{TEXT} .= S ;



10.17. Сортировка почты 375

зующая Date::Manip, работает в 10 раз медленнее предыдущей. Анализ дат в непредсказуемых форматах занимает слишком много времени.

Пример 10.4. datesort

#!/usr/bin/perl -00

# datesort - сортировка почтового ящика по теме и дате

use strict;

use Date::Manip;

my ©msgs = ();

while (<>) {

next unless /"From/m;

my $date = ;

if (/"Date:\s.(..)/m) {

($date = $1) =- s/\s+\(.V/; $date = ParseDate($date);

push ©msgs, {

SUBJECT => /"Sub]ect:\s.(?:Re:\s.).(..)/mi, DATE => Sdate, NUMBER => scalar @msgs, TEXT => ,

} continue {

Smsgs[-1]{TEXT} ,= S ;

for my Smsg (sort {

Sa->{SUBJECT} cmp $b->{SUBJECT) II

Sa->{DATE} cmp Sb->{DATE} II

Sa->{NUMBER} <=> $b->{NUMBER} } @msgs

print $msg->{TEXT};

Особого внимания в примере 10.4 заслуживает блок continue. При достижении конца цикла (нормальном выполнении или переходе по next) этот блок выполняется целиком. Он соответствует третьему компоненту цикла for, но не ограничивается одним выражением. Это полноценный блок, который может состоять из нескольких команд.

> Смотри также-

Описание функции sort в perlfunc{l); описание переменной $/ в perlvar{\) и во введении главы 8 «Содержимое файлов»; рецепты 3.7, 4.15, 5.9 и 11.9.



Ссылки и записи

в эту маленькую паутинку Я поймаю такую большую муху, как Кассио.

Шекспир, «Отелло», акт II, сцена 1

Введение

в Perl существуют три основных типа данных: скалярные величины, массивы и хэши. Конечно, многие программы удается написать и без сложных структур данных, но обычно простых переменных и списков все же оказывается недостаточно.

Три встроенные структуры данных Perl в сочетании со ссылками позволяют строить сколь угодно сложные и функциональные структуры данных - те самые записи, которых так отчаянно не хватало в ранних версиях Perl. Правильно выбирая структуру данных и алгоритм, вы иногда выбираете между элегантной программой, которая быстро снравляется со своей задачей, и убогой поделкой, работающей с черепашьей скоростью и нещадно пожирающей системные ресурсы.

Первая часть этой главы посвящена созданию и использованию простых ссылок. Во второй части рассказывается о применении ссылок для создания структур данных более высокого порядка.

Ссылки

Чтобы хорошо понять концепцию ссылок, сначала необходимо разобраться с тем, как в Perl хранятся значения неременных. С любой определенной неременной ассоциируется имя и адрес области памяти. Идея хранения адресов шрает для ссылок особую роль, поскольку в ссылке хранятся данные о местонахождении другой величины. Скалярная величина, содержащая адрес области памяти, называется ссылкой. Значение, хранящееся в памяти по данному адресу, называется субъектом (referent) (рис. 11.1).

Субъект может относиться к одному из встроенных типов данных (скалярная величина, массив, хэш, ссылка, код или глоб) или представлять собой пользовательский тип, основанный на одном из встроенных типов.



0 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 [ 119 ] 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242