Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Самоучитель по PHP 4

.pdf
Скачиваний:
82
Добавлен:
02.05.2014
Размер:
4.36 Mб
Скачать

Глава 13. Работа с массивами

231

array_count_values() подсчитывает частоту появления значений в списке $List. Вот пример:

$List=array(1, "hello", 1, "world", "hello"); array_count_values($array);

// возвращает array(1=>2, "hello"=>2, "world"=>1)

Комплексная замена в строке

В предыдущей главе мы рассматривали функцию strtr(), которая заменяла в строке одни буквы на другие, и функцию str_replace(), осуществляющую контекстный поиск и замену. В свете ассоциативных массивов эти две функции объединяются в одну, также называющуюся strtr(), но несущую в себе возможности str_replace().

string strtr(string $st, array $Substitutes)

Эта функция (заметьте — с двумя параметрами, а не с тремя, как обычная strtr()!) берет строку $st и проводит в ней контекстный поиск и замену: ищутся подстроки — ключи в массиве $Substitutes — и замещаются на соответствующие им значения. Таким образом, теперь мы можем выполнить несколько замен сразу, не используя str_replace() в цикле:

$Subs=array(

"<name>" => "Larry", "<time>" => date("d.m.Y")

);

$st="Привет, <name>! Сейчас <time>"; echo strtr($st,$Subs);

А вот как можно "отменить" действие функции HtmlSpecialChars():

$Trans=array_flip(get_html_translation_table()); $st=strtr($st, $Trans);

В результате мы из строки, в которой все спецсимволы заменены на их HTMLэквиваленты, получим исходную строку во всей ее первозданной красе. Функции get_html_translation_table() не уделено много внимания в этой книге. Она возвращает таблицу преобразований, которая применяется при вызове

HtmlSpecialChars().

Функция strtr() начинает поиск с самой длинной подстроки и не проходит по одному и тому же ключу дважды.

232

Часть IV. Стандартные функции PHP

Слияние массивов

array array_merge(array $A1, array $A2, ...)

Функция array_merge() призвана устранить все недостатки, присущие оператору + для слияния массивов. А именно, она сливает массивы, перечисленные в ее аргументах, в один большой массив и возвращает результат. Если в массивах встречаются одинаковые ключи, в результат помещается пара ключ=>значение из того массива, который расположен правее в списке аргументов. Однако это не затрагивает числовые ключи: элементы с такими ключами помещаются в конец результирующего массива в любом случае.

Таким образом, с помощью array_merge() мы можем избавиться от всех недостатков оператора + для массивов. Вот пример, сливающий два списка в один:

$L1=array(10,20,30); $L2=array(100,200,300); $L=array_merge($L1,$L2);

// теперь $L===array(10,20,30,100,200,300);

Всегда используйте эту функцию, если вам нужно работать именно со списками, а не с обычными ассоциативными массивами.

Получение части массива

array array_slice(array $Arr, int $offset [, int $len])

Эта функция возвращает часть массива ассоциативного массива, начиная с пары ключ=>значения со смещением (номером) $offset от начала и длиной $len (если последний параметр не задан, до конца массива).

Параметры $offset и $len задаются по точно таким же правилам, как и аналогичные параметры в функции substr(). А именно, они могут быть отрицательными (в этом случае отсчет осуществляется от конца массива), и т. д. Вот несколько примеров из документации PHP:

$input = array ("a", "b", "c", "d", "e");

$output = array_slice ($input, 2);

// "c", "d", "e"

$output = array_slice ($input, 2, -1);

// "c", "d"

$output = array_slice ($input, -2, 1);

// "d"

$output = array_slice ($input, 0, 3);

// "a", "b", "c"

Вставка/удаление элементов

Мы уже знаем несколько операторов, которые отвечают за вставку и удаление элементов. Например, оператор [] (пустые квадратные скобки) добавляет элемент в ко-

Глава 13. Работа с массивами

233

нец массива, присваивая ему числовой ключ, а оператор Unset() вместе с извлечением по ключу удаляет нужный элемент. Язык PHP версии 4 поддерживает и многие другие функции, которые иногда бывает удобно использовать.

int array_push(alist &$Arr, mixed $var1 [, mixed $var2, …])

Эта функция добавляет к списку $Arr элементы $var1, $var2 и т. д. Она присваивает им числовые индексы — точно так же, как это происходит для стандарных []. Если вам нужно добавить всего один элемент, наверное, проще и будет воспользоваться этим оператором:

array_push($Arr,1000);

//

вызываем функцию…

$Arr[]=100;

//

то же самое, но короче

Обратите внимание, что функция array_push() воспринимает массив, как стек, и добавляет элементы всегда в его конец. Она возвращает новое число элементов в массиве.

mixed array_pop(list &$Arr)

Функция array_pop(), а противоположность array_push(), снимает элемент с "вершины" стека (то есть берет последний элемент списка) и возвращает его, удалив после этого его из $Arr. С помощью этой функции мы можем строить конструкции, напоминающие стек. Если список $Arr был пуст, функция возвращает пустую строку.

int array_unshift(list &$Arr, mixed $var1 [, mixed $var2, …])

Функция очень похожа на array_push(), но добавляет перечисленные элементы не в конец, а в начало массива. При этом порядок следования $var1, $var2 и т. д. остается тем же, т. е. элементы как бы "вдвигаются" в список слева. Новым элементам списка, как обычно, назначаются числовые индексы, начиная с 0; при этом все ключи старых элементов массива, которые также были числовыми, изменяются (чаще всего они увеличиваются на число вставляемых значений). Функция возвращает новый размер массива. Вот пример ее применения:

$A=array(10,"a"=>20,30); array_unshift($A,"!","?");

// теперь $A===array(0=>"!", 1=>"?", 2=>10, a=>20, 3=>30)

mixed array_shift(list &$Arr)

Эта функция извлекает первый элемент массива $Arr и возвращает его. Она сильно напоминает array_pop(), но только получает начальный, а не конечный элемент, а также производит довольно сильную "встряску" всего массива: ведь при извлечении первого элемента приходится корректировать все числовые индексы у всех оставшихся элементов…

array array_unique(array $Arr)

234

Часть IV. Стандартные функции PHP

Функция array_unique() возвращает массив, составленный из всех уникальных значений массива $Arr вместе с их ключами. В результирующий массив помещаются первые встретившиеся пары ключ=>значение:

$input=array("a" => "green", "red", "b" => "green", "blue", "red"); $result=array_unique($input);

// теперь $result===array("a"=>"green", "red", "blue");

array array_splice(array &$Arr, int $offset [, int $len] [, int $Repl])

Эта функция, также как и array_slice(), возвращает подмассив $Arr, начиная с индекса $offset максимальной длины $len, но, вместе с тем, она делает и другое полезное действие. А именно, она заменяет только что указанные элементы на то, что находится в массиве $Repl (или просто удаляет, если $Repl не указан). Параметры $offset и $len задаются так же, как и в функции substr() — а именно, они могут быть и отрицательными, в этом случае отсчет начинается от конца массива. За детальными разъяснениями обращайтесь к описанию функции substr(), рассмотренной в предыдущей главе.

Приведу несколько примеров:

$input=array("red", "green", "blue", "yellow"); array_splice($input,2);

//Теперь $input===array("red", "green") array_splice($input,1,-1);

//Теперь $input===array("red", "yellow")

array_splice($input, -1, 1, array("black", "maroon"));

//Теперь $input===array("red", "green", "blue", "black", "maroon") array_splice($input, 1, count($input), "orange");

//Теперь $input===array("red", "orange")

Последний пример показывает, что в качестве параметра $Repl мы можем указать и обычное, строковое значение, а не массив из одного элемента.

Переменные и массивы

array compact(mixed $vn1 [, mixed $vn2, …])

Функция compact(), впервые появившаяся в PHP версии 4, упаковывает в массив переменные из текущего контекста (глобального или контекста функции), заданные своими именами в $vn1, $vn2 и т. д. При этом в массиве образуются пары с ключами, равными содержимому $vnN, и значениями соответствующих переменных. Вот пример использования этой функции:

$a="Test string";

Глава 13. Работа с массивами

235

$b="Some text"; $A=compact("a","b");

// теперь $A===array("a"=>"Test string", "b"=>"Some text")

Почему же тогда параметры функции обозначены как mixed? Дело в том, что они могут быть не только строками, но и списками строк. В этом случае функция последовательно перебирает все элементы этого списка, и упаковывает те переменные из текущего контекста, имена которых она встретила. Более того — эти списки могут, в свою очередь, также содержать списки строк, и т. д. Правда, последнее используется сравнительно редко, но все же вот пример:

$a="Test"; $b="Text"; $c="CCC"; $d="DDD";

$Lst=array("b",array("c","d")); $A=compact("a",$Lst);

// теперь $A===array("a"=>"Test", "b"=>"Text", "c"=>"CCC", "d"=>"DDD")

void extract(array $Arr [, int $type] [, string $prefix])

Эта функция производит действия, прямо противоположные compact(). А именно, она получает в параметрах массив $Arr и превращает каждую его пару ключ=>значение в переменную текущего контекста.

Параметр $type предписывает, что делать, если в текущем контексте уже существует переменная с таким же именем, как очередной ключ в $Arr. Он может быть равен одной из констант, перечисленных в табл. 13.1

Таблица 13.1. Поведение функции extract в случае совпадения переменных

Константа

Действие

 

 

EXTR_OVERWRITE

Переписывать существующую переменную (по умолчанию)

EXTR_SKIP

Не перезаписывать переменную, если она уже существует

EXTR_PREFIX_SAME

В случае совпадения имен создавать переменную с име-

 

нем, предваренным префиксом из $prefix. Надо сказать,

 

что на практике этот режим должен быть совершенно бес-

 

полезен

EXTR_PREFIX_ALL

Всегда предварять имена создаваемых переменных пре-

 

фиксом $prefix

По умолчанию подразумевается EXTR_OVERWRITE, т. е. переменные перезаписываются. Вот пара примеров применения этой функции:

// Сделать все переменные окружения глобальными

236

Часть IV. Стандартные функции PHP

extract($HTTP_ENV_VARS);

// То же самое, но с префиксом E_ extract($HTTP_ENV_VARS, EXTR_PREFIX_ALL, "E_");

echo $E_COMSPEC; // выводит переменную окружения COMSPEC

Параметр $prefix имеет смысл указывать только тогда, когда вы применяете режимы EXTR_PREFIX_SAME или EXTR_PREFIX_ALL.

Вообще говоря, использование extract() и compact() может быть оправдано лишь для небольших массивов, да и то только в шаблонах, а в остальных случаях считается признаком дурного тона. Впрочем, если ваш дизайнер никак не может понять, зачем же ему в шаблонах страниц гостевой книги указывать все эти ужасные квадратные скобки и апострофы, можете пойти ему навстречу так:

<table width=100%>

<?foreach($Book as $Entry) { extract($Entry)?> <tr>

<td>Имя: <?=$name?></td> <!-- вместо $Entry['name'] --> <td>Адрес: <?=$url?></td> <!-- вместо $Entry['url'] -->

</tr>

<tr><td colspan=3><?=$text?></td></tr> <tr><td colspan=3><hr></td></tr>

<?}?>

</table>

Здесь вы должны загодя позаботиться, чтобы ключи $Entry ненароком не затерли нужные переменные. Этого можно добиться, например, назвав все важные переменные с прописной буквы (например, $Book и $Entry), а все ключи — с маленькой, как и было сделано немного выше.

Создание списка – диапазона чисел

list range(int $low, int $high)

Эта функция очень простая. Она создает список, заполненный целыми числами от $low до $high включительно. Ее удобно применять, если мы хотим быстро сгенерировать массив для последующего прохождения по нему циклом foreach:

<table>

<?foreach(range(1,100) as $i) {?> <tr>

<td><?=$i?></td>

Глава 13. Работа с массивами

237

<td>Это строка номер <?=$i?></td> </tr>

<?}?>

</table>

С точки зрения дизайнеров (не знакомых с PHP, но которым придется модифицировать внешний вид вашего сценария) представленный подход выглядит явно лучше, чем следующий фрагмент:

<table>

<?for($i=1; $i<=100; $i++) {?> <tr>

<td><?=$i?></td>

<td>Это строка номер <?=$i?></td> </tr>

<?}?>

</table>

Глава 14

Математические

функции

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

Встроенные константы

PHP версии 4 предлагает нам несколько предопределенных констант, которые обозначают различные математические постоянные с максимальной машинной точностью. Соответствующие этим константам ключевые слова и значения приводятся в табл. 14.1.

 

Таблица 14.1. Математические константы.

 

 

 

Константа

Величина

Пояснение

 

 

 

M_PI

3,14159265358979323846

Число π

M_E

2,7182818284590452354

e

M_LOG2E

1,4426950408889634074

Log2(e)

M_LOG10E

0,43429448190325182765

Lg(e)

M_LN2

0,69314718055994530942

Ln(2)

M_LN10

2,30258509299404568402

Ln(10)

M_PI_2

1,57079632679489661923

π /2

M_PI_4

0,78539816339744830962

π /4

M_1_PI

0,31830988618379067154

1/ π

M_2_PI

0,63661977236758134308

2/ π

M_SQRTPI

1,77245385090551602729

sqrt(π)

M_2_SQRTPI

1,12837916709551257390

2/sqrt(π)

 

Глава 14. Математические функции

239

 

M_SQRT2

1,41421356237309504880

sqrt(2)

 

 

 

Таблица 14.1 (окончание)

 

 

 

 

 

 

Константа

Величина

Пояснение

 

 

 

 

 

 

M_SQRT3

1,73205080756887729352

sqrt(3)

 

M_SQRT1_2

0,70710678118654752440

1/sqrt(2)

 

M_LNPI

1,14472988584940017414

Ln(π)

 

M_EULER

0,57721566490153286061

Постоянная Эйлера

Надо заметить, разработчики PHP что-то слишком разошлись, когда вводили стандартные константы. Например, я не могу даже и представить, зачем в Webпрограммировании может потребоваться, например, константа Эйлера. Что же, это их право….

Функции округления

mixed abs(mixed $number)

Возвращает модуль числа. Тип параметра $number может быть float или int, а тип возвращаемого значения всегда совпадает с типом этого параметра.

double round(double $val)

Округляет $val до ближайшего целого и возвращает результат, например: $foo = round(3.4); // $foo == 3.0

$foo = round(3.5); // $foo == 4.0 $foo = round(3.6); // $foo == 4.0

int ceil(float $number)

Возвращает наименьшее целое число, не меньшее $number. Разумеется, передавать в $number целое число бессмысленно.

int floor(float $number)

Возвращает максимальное целое число, не превосходящее $number.

Случайные числа

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

240

Часть IV. Стандартные функции PHP

Я намеренно не рассматриваю функции rand() и srand(), потому что каче- ство случайных чисел, которые они выдают, никуда не годится. Настоятельно рекомендую вместо них использовать описанные ниже функции, а про rand() вообще забыть.

int mt_rand(int $min=0, int $max=RAND_MAX)

Функция возвращает случайное число, достаточно равномерно даже для того, чтобы использовать ее в криптографии. Подробнее о том алгоритме, который она использует, можно прочитать в Интернете по адресу http://www.math.keio.ac.jp/~matumoto/emt.html, а исходные тексты найти по адресу http://www.scp.syr.edu/~marc/hawk/twister.html. Если вы хотите генерировать числа не от 0 до RAND_MAX (эта константа задает максимально допустимое случайное число, и ее можно получить при помощи вызова mt_getrandmax()), задайте соответствующий интервал в параметрах $min и $max.

Не забудьте только перед первым вызовом этой функции запустить mt_srand().

Давайте теперь рассмотрим один из случаев применения функции mt_rand(). Речь пойдет об извлечении строки со случайным номером из текстового файла (работу с файлами мы рассмотрим чуть позже, а пока скажу лишь, что функция fget() читает очередную строку из файла, дескриптор которого указан ей в первом параметре, а второй параметр задает максимально возможную длину этой строки, для нас это — очень большое число). Поступим так:

for($i=0; mt_rand(0,$i)<1; $i++) $s=fgets($OurFile,10000);

echo "Случайная строка: $s";

Этот способ работает в строгом соответствии с теорией вероятностей: для первой строки вероятность ее извлечения будет 100%, для второй — 50% (она перепишется поверх первой), для третьей — 33%, и т. д. Например, если файл состоит всего из трех строк, то вероятность извлечения третьей строки, как мы уже заметили, будет равна 33%, а значит, первой или второй — соответственно, 66%. Но вероятность извлечения второй строки после первой равна 50%, а 50% от 66% будет также 33%, т. е. вероятность извлечения каждой строки одинакова. Мы видим, что для файла из трех строк алгоритм работает правильно. Не вдаваясь в математические подробности, скажу, что он работает верно и для любого количества строк.

Безусловно, мы могли бы загрузить весь файл в память и выбрать из него нужную строку и при помощи одного-единственного вызова mt_rand(), но если файл содержит очень много данных, это может быть довольно не экономично с точки зрения расхода памяти. Наоборот, для случая коротких файлов способ единовременной загрузки предпочтительнее. Насколько коротких? Думаю, это легче всего определить опытным путем. Рассмотренный нами способ решает проблему с большими файлами.