Глава 5. Массивы в PHP

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

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

Создание массивов

Массив представляет собой совокупность объектов, имеющих одинаковый размер и тип. Каждый объект в массиве называется элементом массива. Создать новый массив в PHP несложно. При объявлении индексируемого массива после имени переменной ставится пара квадратных скобок ([]):

$languages[] = "Spanish";
// $languages[0] = "Spanish"

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

$languages[] = "English"; // $languages[1] = "English";
$languages[] = "Gaelic"; // $languages[2] = "Gaelic";

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

$languages[15] = "Italian";
$languages[22] = "French";

Ассоциативные массивы создаются аналогичным образом:

$languages["Spain"] = "Spanish";
$languages["France"] = "French";

При создании массивов используются три стандартные языковые конструкции:

Хотя все три случая приводят к одному результату — созданию массива, в некоторых случаях одна конструкция может оказаться предпочтительнее других. Далее приведены описания и примеры использования каждой конструкции.

аггау()

Функция array() получает ноль или более элементов и возвращает массив, состоящий из указанных элементов. Ее синтаксис:

array array ( [элемент1, элемент2...] )

Вероятно, array() является всего лишь более наглядной записью для создания массива, используемой для удобства программиста. Ниже показан пример использования array() для создания индексируемого массива:

$languages = array ("English". "Gaelic". "Spanish");
// $languages[0] = "English". $languages[1] = "Gaelic",
// $languages[2] = "Spanish"

А вот как array() используется при создании ассоциативных массивов:

$languages = array("Spain" => "Spanish",
"Ireland" => "Gaelic".
"United States" => "English");
// $languages["Spain"] = "Spanish"
// $languages["Ireland"] = "Gaelic"
// $languages["United States"] = "English"

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

list()

Конструкция list() похожа на array(), однако ее главная задача — одновременное присваивание значений, извлеченных из массива, сразу нескольким переменным. Синтаксис команды list():

void list (переменная1 [. переменная2 , ...] )

Конструкция list() особенно удобна при чтении информации из базы данных или файла. Допустим, вы хотите отформатировать и вывести данные, прочитанные из текстового файла. Каждая строка файла содержит сведения о пользователе (имя, профессия и любимый цвет); компоненты записи разделяются вертикальной чертой (|). Типичная строка выглядит так:

Nino Sanzi|Professional Golfer|green

При помощи list() можно написать простой цикл, который будет читать каждую строку, присваивать ее компоненты переменным, форматировать и отображать данные. Приведенный ниже листинг демонстрирует возможность одновременного присваивания нескольким переменным с использованием list():

// Читать строки, пока не будет достигнут конец файла
while ($line = fgets($user_file, 4096)) {
    // Разделить строку функцией explode().
    // Компоненты присваиваются переменным $name, $occupation и $color.
    list($name, $occupation, $color) = explode("|", $line);
    // Отформатировать и вывести данные
    echo "Name: $name <br>";
    echo "Occupation: $occupation <br>";
    echo "Favorite color: $color <br>";
}

Каждая строка файла читается, форматируется и выводится в следующем виде:

Name: Nino Sanzi
Occupation: Professional Golfer
Favorite color: green

В приведенном примере применение list() зависит от разделения строки на элементы функцией split(). Элементы, полученные в результате деления, присваиваются, соответственно, переменным $name, $occupation и $color. Дальше все сводится к форматированию данных для вывода в конкретном браузере. Удобные средства лексического анализа текстовых файлов являются одной из сильных сторон РНР. Эта тема подробно рассматривается в главе 7 и главе 8.

range()

Конструкция range() позволяет легко и быстро создать массив целых чисел из интервала, определяемого верхней и нижней границами. Range() возвращает массив, состоящий из всех целых чисел указанного интервала. Синтаксис range():

array range(int нижняя_граница, int верхняя граница);

Следующий пример наглядно показывает, насколько удобна эта конструкция:

$lottery = range(0,9);
// $lottery = array(0,1,2,3,4,5,6,7,8,9)

Как видно из приведенного фрагмента, в параметрах range() был указан интервал от 0 до 9 и массив $lottery был заполнен целыми числами из этого интервала.

Многомерные массивы

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

$chessboard[1][4] = "King"; // Двухмерный массив
$capitals["USA"] ["Ohio"] = "Columbus": // Двухмерный массив
$streets["USA"]["Ohio"]["Columbus"] = "Harrison"; // Трехмерный массив

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

$desserts = аrrау(
    "Fruit Cup" => array (
        "calories" => "low",
        "served" -> "cold",
        "preparation" => "10 minutes"
    ),
    "Brownies" => array (
        "calories" -> "high",
        "served" => "piping hot",
        "preparation" => "45 minutes"
    )
);

После создания массива к его элементам можно обращаться по соответствующим ключам:

$desserts["Fruit Cup"]["preparation"] // возвращает "10 minutes"
$desserts["Brownies"]["calories"] // возвращает "high"

Присваивание значений элементам многомерных массивов выполняется так же, как и в одномерных массивах:

$desserts["Cake"]["calories"] = "too many";
// Присваивает свойству "calories" объекта "Cake" значение "too many"

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

Ссылки на многомерные массивы

Ссылки на элементы многомерных массивов внутри строк несколько отличаются от ссылок на другие типы данных. Возможны два варианта. Во-первых, можно воспользоваться оператором конкатенации:

print "Brownies are good, but the calories content is ";
$desserts["Brownies"]["calories"];

Во-вторых, ссылку на элемент многомерного массива можно заключить в фигурные скобки { }:

print "Brownies are good, but the calories content is
{$desserts[Brownies][calories]}";

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

Поиск элементов массива

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

in_array()

Функция in_array() проверяет, присутствует ли в массиве заданный элемент. Если поиск окажется удачным, функция возвращает TRUE, в противном случае возвращается FALSE. Синтаксис функции in_array():

bool in_array(mixed элемент, array массив)

Эта функция особенно удобна тем, что вам не приходится в цикле перебирать весь массив в поисках нужного элемента. В следующем примере функция in_array() ищет элемент "Russian" в массиве $languages:

$languages = array("English", "Gaelic", "Spanish"):
$exists = in_array("Russian", $languages); // $exists присваивается FALSE
$exists = in_array("English", $languages): // $exists присваивается TRUE

Функция in_array() часто встречается в управляющих конструкциях, когда ее возвращаемое значение (TRUE/FALSE) используется для выбора одного из двух вариантов продолжения. В следующем примере функция in_array() используется для выбора одного из двух вариантов в условной команде if:

// Ввод данных пользователем
$language = "French"; $email = "wjgilmore@hotmail.com";
// Если язык присутствует в массиве
if (in_array($language. $languages)) :
// Подписать пользователя на бюллетень.
// Обратите внимание: в РНР нет стандартной функции с именем
// subscribe_user(). В данном примере эта функция просто имитирует
// процесс подписки.
subscribe_user($email, $language);
print "You are now subscribed to the $language edition of the newsletter.";
// Язык отсутствует в массиве
else :
print "We're sorry, but we don't yet offer a $language edition of the newsletter".
endif;

Что происходит в этом примере? Допустим, переменные $language и $email содержат данные, введенные пользователем. Вы хотите убедиться в том, что указанный язык поддерживается вашей системой, и используете для этой цели функцию in_array(). Если название языка присутствует в массиве, пользователь подписывается на бюллетень и получает соответствующее сообщение. В противном случае программа сообщает, что на указанном языке бюллетень не распространяется. Конечно, в настоящей программе пользователь не должен гадать, какие языки поддерживаются вашей программой. Задача решается при помощи раскрывающегося списка — эта тема подробно рассматривается в главе 10. Здесь этот пример всего лишь демонстрирует возможности работы с массивами.

array_keys()

Функция array_keys() возвращает массив, содержащий все ключи исходного массива, переданного в качестве параметра. Если при вызове передается дополнительный параметр искомый_элемент, возвращаются только ключи, которым соответствует заданное значение; в противном случае возвращаются все ключи массива. Синтаксис функции array_keys():

array array_keys (array массив [, mixed искомый_элемент])

Рассмотрим пример использования функции array_keys() для получения ключа заданного элемента:

$great_wines = array ("Australia" => "Clarendon Hills 96",
"France" => "Comte George de Vogue 97",
"Austria" => "Feiler Artinger 97");
$great_labels = array_keys($great_wines);
// $great_labels = array("Australia", "France", "Austria");
$great_labels = array_keys($great_wines, "Clarendon Hills 96");
// $great_labels = array("Australia");

Функция array_keys() позволяет очень легко получить все ключи ассоциативного массива — например, в предыдущем случае ими были названия стран, в которых производятся различные сорта вин.

array_values()

Функция array_values() возвращает массив, состоящий из всех значений исходного массива, переданного в качестве параметра. Синтаксис функции array_values():

array array_values(array массив)

Вернемся к предыдущему примеру, в котором функция array_keys() использовалась для получения всех значений ключей. На этот раз функция array_values() возвращает все значения, соответствующие ключам:

// $great_wines = array ("Australia" => "Clarendon Hills 96",
// "France" => "Comte George de Vogue 97",
// "Austria" => "Feiler Artinger 97");
$great_labels = array_values($great_wines);
// $great_labels = аrrау("Clarendon Hills 96",
// "Comte George de Vogue 97",
// "Feiler Artinger 97");

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

Добавление и удаление элементов

К счастью, в РНР при создании массива не нужно указывать максимальное количество элементов. Это увеличивает свободу действий при операциях с массивами, поскольку вам не приходится беспокоиться о случайном выходе за границы массива, если количество элементов превысит ожидаемый порог. В РНР существует несколько функций для увеличения размеров массива. Некоторые из них были созданы для удобства программистов, привыкших работать с различными типами очередей и стеков (FIFO, FILO и т. д.), что отражается в названиях функций (push, pop, shift и unshift). Но даже если вы не знаете, что такое «очередь» или «стек», не огорчайтесь — в этих функциях нет ничего сложного.

Очередью (queue) называется структура данных, из которой элементы извлекаются в порядке поступления. Стеком (stack) называется структура данных, из которой элементы извлекаются в порядке, обратном порядку их поступления.

array_push()

Функция array_push() присоединяет (то есть дописывает в конец массива) один или несколько новых элементов. Синтаксис функции array_push():

int array_push(array массив, mixed элемент [, ...])

Длина массива возрастает прямо пропорционально количеству его элементов. Это продемонстрировано в следующем примере:

$languages = array("Spanish", "English", "French");
array_push($languages, "Russian", "German", "Gaelic");
// $languages = array("Spanish", "English", "French",
// "Russian", "German", "Gaelic")

У функции array_push(), как и у многих стандартных функций РНР, существует «двойник» — функция аrrау_рор(), предназначенная для извлечения элементов из массива. Главное различие между этими функциями заключается в том, что array_push() может добавлять несколько элементов одновременно, а аrrау_рор() удаляет элементы только по одному.

аrrау_рор()

Результат работы функции аrrау_рор() прямо противоположен array_push() — эта функция извлекает (то есть удаляет) последний элемент из массива. Извлеченный элемент возвращается функцией. Синтаксис функции аrrау_рор():

аrrау_рор(аrrау массив)

При каждом выполнении аrrау_рор() размер массива уменьшается на 1. Рассмотрим пример:

$languages = array("Spanish", "English", "French",
"Russian", "German", "Gaelic");
$a_language = array_pop($languages): // $a_language = "Gaelic"
$a_language = array_pop($languages): // $a_language = "German"
// $languages = array ("Spanish", "English", "French", "Russian");

Функции array_push(), и array_pop() удобны тем, что с их помощью можно выполнять операции с элементами и управлять размером массива, не беспокоясь о неинициализированных или пустых элементах. Такое решение работает намного эффективнее, чем любые попытки управления этими факторами со стороны программиста.

array_shift()

Функция array_shift() аналогична аrrау_рор() с одним отличием: элемент удаляется из начала (левого края) массива. Все остальные элементы массива сдвигаются на одну позицию к началу массива. У функции array_shift() такой же синтаксис, как и у аггау_рор():

array_shift(array массив)

При работе с функцией array_shift() необходимо помнить, что элементы удаляются из начала массива, как показывает следующий пример:

$languages = array("Spanish", "English", "French", "Russian");
$a_language = array_shift($languages); // $a_language = "Spanish";
// $languages = array("English", "French", "Russian");

array_unshift()

Функция array_unshift() дополняет array_shift() — новый элемент вставляется в начало массива, а остальные элементы сдвигаются на одну позицию вправо. Синтаксис команды array_unshift():

int array_unshift(array массив, mixed переменная1 [....переменная2])

При одном вызове функции можно добавить как один, так и несколько элементов, при этом размер массива возрастает пропорционально количеству добавленных элементов. Пример добавления нескольких элементов:

$languages = array("French", "Italian", "Spanish");
array_unshift($languages, "Russian", "Swahili", "Chinese");
// $languages = array("Russian", "Swahili", "Chinese",
// "French", "Italian", "Spanish");

array_pad()

Функция array_pad() позволяет быстро увеличить массив до желаемого размера посредством его дополнения стандартными элементами. Синтаксис функции array_pad():

array arrap_pad(array массив, int размер, mixed значение);

Параметр размер определяет новую длину массива. Параметр значение задает стандартное значение, присваиваемое элементам во всех новых позициях массива. При использовании array_pad() необходимо учитывать некоторые обстоятельства:

Если размер положителен, массив дополняется справа, а если отрицателен — слева.

Если абсолютное значение параметра размер меньше либо равно длине массива, никаких действий не выполняется.

Абсолютным значением (модулем) целого числа называется его значение без знака. Например, абсолютное значение чисел 5 и -5 равно 5.

Пример дополнения массива с конца:

$weights = array(1, 3, 5, 10, 15, 25, 50);
$weights = array_pad($weights. 10, 100);
// Результат: $weights = array(1, 3, 5, 10, 15, 25, 50, 100, 100, 100);
Пример дополнения массива с начала:
$weights = array(1, 3, 5, 10, 15, 25, 50);
$weights = array_pad($weights, -10, 100);
// Результат: $weights = array(100, 100, 100, 1, 3, 5, 10, 15, 25, 50);
Неправильная попытка дополнения массива:
$weights = array(1, 3, 5, 10, 15, 25, 50);
$weights = array_pad($weigtits, 3, 100);
// Массив $weights не изменяется:
// $weights = array(1, 3, 5, 10, 15, 25, 50);

Перебор элементов

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

reset()

Функция reset() переводит внутренний указатель текущей позиции в массиве к первому элементу. Кроме того, она возвращает значение первого элемента. Синтаксис функции reset():

mixed reset (array массив)

Рассмотрим следующий массив:

$fruits = array("apple", "orange", "banana");

Допустим, указатель текущей позиции в этом массиве установлен на элемент "orange". Команда:

$a_fruit = reset($fruits);

вернет указатель в начало массива, то есть на элемент "apple", и вернет это значение, если результат вызова reset() используется в программе. Возможен и упрощенный вариант вызова:

reset($fruits);

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

each()

Функция each() при каждом вызове выполняет две операции: она возвращает пару «ключ/значение», на которую ссылается указатель текущей позиции, и перемещает указатель к следующему элементу. Синтаксис функции each():

array each(array массив)

Для удобства each() возвращает ключ и значение в виде массива из четырех элементов; ключами этого массива являются 0, 1, value и key. Возвращаемый ключ ассоциируется с ключами 0 и key, а возвращаемое значение — с ключами 1 и value.

В следующем примере функция each() возвращает элемент, находящийся в текущей позиции:

// Объявить массив из пяти элементов

$spices = array("parsley", "sage", "rosemary", "thyme", "pepper");
// Установить указатель на первый элемент массива
reset($spices);

// Создать массив $a_sp1ce. состоящий из четырех элементов

$a_spice = each($spices);

В результате выполнения приведенного фрагмента массив $a_spice будет содержать следующие пары «ключ/значение»:

После этого строку "parsley" можно вывести любой из следующих команд:

print $a_spice[1]: print $a_spice["value"];

Функция each() обычно используется в сочетании с list() в циклических конструкциях для перебора всех или некоторых элементов массива. При каждой итерации each() возвращает либо следующую пару «ключ/значение», либо логическую ложь при достижении последнего элемента массива. Вернемся к массиву $spices; чтобы вывести все элементы на экран, можно воспользоваться следующим сценарием:

// Сбросить указатель текущей позиции
reset($spices);
// Перебрать пары "ключ/значение", ограничиваясь выводом значения
while (list ($key, $val) = each ($spices) ) :
print "$val <br>"
endwhile;

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

Листинг 5.1. Построение таблицы HTML по содержимому массива:

// Объявить ассоциативный массив стран и языков
$languages = array(
    "Country" => "Language",
    "Spain" => "Spanish",
    "USA" => "English",
    "France" => "French",
    "Russia" => "Russian"
);
// Начать новую таблицу
print "<table border=l>";
// Переместить указатель к позиции первого элемента
reset ($languages);
// Прочитать первый ключ и элемент
$hdl = key ($languages);
Shd2 = $languages[$hd1];
// Вывести первый ключ и элемент в виде заголовков таблицы
print "<tr><th>$hd1</th><th>$hd2</th></tr>";
next($languages);
// Выводить строки таблицы с ключами и элементами массива
while (list ($ctry,$lang) = each ($languages)) :
print "<tr><td>Sctry</td><td>$lang</td></tr>";
endwhile;
// Завершить таблицу print "</table>";
?>

В результате выполнения этого кода будет построена следующая таблица HTML.

CountryLanguage
SpainSpanish
USAEnglish
FranceFrench
RussiaRussian

Этот пример дает представление о самой сильной стороне РНР — возможности объединения динамического кода с HTML для получения наглядного, отформатированного представления прочитанных данных.

end()

Функция end() перемещает указатель к позиции последнего элемента массива. Синтаксис функции end():

end(array массив)

next()

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

mixed next(array массив)

Недостаток функции next() заключается в том, что ложное значение возвращается и для существующих, но пустых элементов массива. Если вы хотите провести обычный перебор, воспользуйтесь функцией each().

prev()

Функция prev() аналогична next() за одним исключением: указатель смещается на одну позицию к началу массива, после чего возвращается элемент, находящийся в новой позиции. Если в результате смещения указатель окажется перед первым элементом массива, prev() вернет ложное значение. Синтаксис функции prev():

mixed prev (array массив)

Недостаток функции prev() заключается в том, что ложное значение возвращается и для существующих, но пустых элементов массива. Если вы хотите провести обычный перебор, воспользуйтесь функцией each().

array_walk()

Функция array_walk() позволяет применить функцию к нескольким (а возможно, всем) элементам массива. Синтаксис функции array_walk():

int array_walk(array массив, string имя_функции [, mixed данные])

Функция, заданная параметром имя_функции, может использоваться для различных целей — например, для поиска элементов с определенными характеристиками или модификации содержимого массива. В ассоциативных массивах функция имя_функции должна получать минимум два параметра — элемент массива и ключ. Если указан необязательный третий параметр данные, он становится третьим параметром. В следующем примере функция array_walk() используется для удаления дубликатов из массива:

function delete_dupes($element) {
    static $last = "";
    if ($element == $last) {
        unset($element);
    } else {
        $last = $element;
    }
}

$emails = array("blah@blah.com", "chef@wjgilmore.com", "blah@blah.com");
sort($emails);
reset($emails);
array_walk($emails, "delete_dupes");
// $emails = array("chef@wjgilmore.com", "blah@blah.com");

array_reverse()

Функция array_reverse() позволяет легко перейти к противоположному порядку элементов, составляющих массив. Синтаксис функции array_reverse():

array array_reverse(array массив)

Рассмотрим пример использования функции array_reverse():

$us_wireproducers = array ("California", "Oregon", "New York". "Washington");
$us_wine_producers = array_reverse ($us_wireproducers);
// $us_wine_producers = array ("Washington". "New York", "Oregon". "California");

При вызове array_reverse() для ассоциативного массива пары «ключ/значение» сохраняются, изменяется только порядок элементов массива.

array_flip()

Функция array_flip() меняет местами ключи и значения элементов массива. Синтаксис функции array_flip():

array array_flip(array массив)

В следующем примере функция array_flip() меняет местами все ключи и значения элементов:

$languages = array("Spain" => "Spanish", "France" => "French", "Italy" => "Italian");
$languages = array_flip($languages);
// $languages = array("Spanish" => "Spain", // "French" => "France", // "Italian" => "Italy");

Помните: функция array_flip() не изменяет порядок элементов массива. Для этой цели используется функция array_reverse().

Размер массива

Наличие информации о текущем размере массива часто позволяет повысить эффективность сценария. Вероятно, размер массива чаще всего используется при циклическом переборе элементов:

$us_wine_producers = array ("Washington", "New York", "Oregon", "California");
for ($i = 0; $i < sizeof($us_wine_producers); $i++) {
    print "$us_wine_producers[$i]";
}

Поскольку массив $us_wine_producers индексируется целыми числами, мы можем воспользоваться циклом for для циклического увеличения переменной-счетчика ($i) и вывода каждого элемента в массиве.

sizeof()

Функция sizeof() возвращает количество элементов в массиве. Синтаксис функции sizeof():

int sizeof(array массив)

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

$pasta = array("bowties", "angelhair", "rigatoni");
$pasta_size = sizeof($pasta);
// $pasta_size = 3

У функции sizeof() существует и другая, расширенная форма — count() (см. ниже).

count()

Функция count() выполняет ту же операцию, что и sizeof(), — она возвращает количество значений, содержащихся в массиве. Синтаксис функции count():

int count(mixed переменная)

Единственное различие между sizeof() и count() заключается в том, что в некоторых ситуациях count() возвращает дополнительную информацию:

array_count_values()

Функция array_count_values() является разновидностью sizeof() и count(). Вместо общего количества элементов она подсчитывает количество экземпляров каждого значения в массиве. Синтаксис функции array_count_values():

array array_count_values(array массив);

В возвращаемом массиве ключами будут значения исходного массива, а значениями — их частоты:

$states = аrrау("ОН", "ОК", "СА", "РА", "ОН", "ОН", "РА", "АК");
$state_freq = array_count_values($states);

Массив $state_freq заполняется следующими ассоциативными парами «ключ/значение»:

$state_freq = аrrау("ОН" => 3, "ОК" => 1, "СА" => 1, "РА" => 2, "АК" => 1);

Сортировка массивов

Сортировка занимает важное место в программировании и часто встречается на практике в таких Интернет-приложениях, как коммерческие сайты (сортировка категорий товаров в алфавитном порядке, сортировка цен) или поисковые системы (сортировка программ по количеству загрузок). В РНР существует девять стандартных функций сортировки (табл. 5.1), причем каждая функция сортирует массив особым образом.

Таблица 5.1. Функции сортировки

ФункцияСортировкаОбратный порядокСохранение пар «ключ/значение»
sortЗначениеНетНет
rsortЗначениеДаНет
asortЗначениеНетДа
arsortЗначениеДаДа
ksortКлючНетДа
krsortКлючДаДа
usortЗначение?Нет
uasortЗначение?Да
uksortКлюч?Да

Относится к применению пользовательских функций сортировки, когда порядок сортировки массива зависит от результатов, возвращаемых пользовательской функцией.

Сортировка элементов массива не ограничивается стандартными критериями, поскольку три функции (usort(), uasort() и uksort()) позволяют задать пользовательский критерий и отсортировать информацию произвольным образом.

sort()

Простейшая функция sort() сортирует элементы массива по возрастанию (от меньших к большим). Синтаксис функции sort():

void sort (array массив)

Нечисловые элементы сортируются в алфавитном порядке в соответствии с ASCII-кодами. Следующий пример демонстрирует применение функции sort() при сортировке:

// Создать массив городов.
$cities = array("Aprilia", "Nettuno", "Roma", "Venezia", "Anzio");
// Отсортировать города по возрастанию
sort($cities);
// Перебрать содержимое массива и вывести все пары "ключ/значение".
for (reset($cities); $key = key ($cities); next ($cities)):
    print("cities[$key] = $cities[$key] <br>");
endfor;

Этот фрагмент выводит следующий результат:

cities[0] = Anzio
cities[1] = Aprilia
cities[2] = Nettuno
cities[3] = Roma
cities[4] = Venezia

Как видите, массив $cities сортируется в алфавитном порядке. Одна из разновидностей этого способа сортировки реализована в функции asort(), описанной ниже.

rsort()

Функция rsort() работает точно так же, как функция sort(), за одним исключением: элементы массива сортируются в обратном порядке. Синтаксис функции rsort():

void rsort(array массив)

Вернемся к массиву $cities из предыдущего примера:

$cities = array("Aprilia", "Nettuno", "Roma", "Venezia", "Anzio");
rsort($cities);

В результате сортировки массива $cities функцией rsort() элементы будут расположены в следующем порядке:

cities[0] = Venezia
cities[1] = Roma
cities[2] = Nettuno
cities[3] = Aprilia
cities[4] = Anzio

Массив $cities также сортируется, но на этот раз в порядке, обратном алфавитному. Одна из разновидностей этого способа сортировки реализована в функции arsort(), описанной ниже.

asort()

Функция asort() работает почти так же, как упоминавшаяся выше функция sort(), однако она сохраняет исходную ассоциацию индексов с элементами независимо от нового порядка элементов. Синтаксис функции asort():

void asort(array массив)

Вернемся к массиву $cities:

$cities = array("Aprilia", "Nettuno", "Roma", "Venezia", "Anzio");
asort($cities);

В результате сортировки массива $cities функцией asort() элементы будут расположены в следующем порядке:

cities[4] = Anzio
cities[0] = Aprilia
cities[1] = Nettuno
cities[2] = Roma
cities[3] = Venezia

Обратите внимание на индексы и сравните их с приведенными в описании функции sort(). Именно в этом и состоит различие между двумя функциями.

arsort()

Функция arsort() представляет собой разновидность asort(), которая сохраняет исходную ассоциацию индексов, но сортирует элементы в обратном порядке. Синтаксис функции arsort():

void arsort(array массив)

Воспользуемся функцией arsort() для сортировки массива $cities:

$cities = array("Aprilia", "Nettuno", "Roma", "Venezia", "Anzio");
arsort($cities);

В результате сортировки элементы будут расположены в следующем порядке:

cities[3] = Venezia
cities[2] = Roma
cities[l] = Nettuno
cities[0] = Aprilia
cities[4] = Anzio

Обратите внимание на индексы и сравните их с приведенными в описании функции rsort(). Именно в этом и состоит различие между двумя функциями.

ksort()

Функция ksort() сортирует массив по ключам, сохраняя исходные ассоциации ключей со значениями. Синтаксис функции ksort():

void ksort(array массив)

Для примера рассмотрим массив, слегка отличающийся от исходного массива:

$wine_producers = array(
    "America" => "Napa Valley",
    "Italy" => "Tuscany",
    "Australia" => "Ruthgerlen",
    "France" => "Loire",
    "Chile" => "Rapel Valley"
);

В результате сортировки массива функцией ksort() элементы будут расположены в следующем порядке:

"America" => "Napa Valley"
"Australia" => "Ruthgerlen"
"Chile" => "Rapel Valley"
"France" => "Loire"
"Italy" => "Tuscany"

Сравните с результатами сортировки $wine_producers функцией sort():

"America" => "Napa Valley"
"Australia" => "Tuscany"
"Chile" => "Ruthgerlen"
"France" => "Loire"
"Italy" => "Rapel Valley"

Более чем сомнительный результат!

krsort()

Функция krsort() почти аналогична ksort(), однако ключи сортируются в обратном порядке. Синтаксис функции krsort():

void krsort(array $массив);

Рассмотрим сортировку массива $wine_producers функцией krsort():

$wine_producers = array (
    "America" => "Napa Valley",
    "Italy" => "Tuscany",
    "Australia" => "Ruthgerlen",
    "France" => "Loire",
    "Chile" => "Rapel Valley"
);
krsort($wine_producers);

В результате сортировки элементы будут расположены в следующем порядке:

"Italy" => "Tuscany"
"France" => "Loire"
"Chile" => "Rapel Valley"
"Australia" => "Ruthgerlen"
"America" => "Napa Valley"

Вероятно, описанных выше функций сортировки будет вполне достаточно для большинства случаев. Тем не менее, в некоторых ситуациях может возникнуть необходимость в определении собственных критериев сортировки. В PHP такая возможность реализована в трех стандартных функциях: usort(), uasort() и uksort().

usort()

Функция usort() дает возможность отсортировать массив на основании критерия, определяемого программистом. Для этого usort() в качестве параметра передается имя функции, определяющей порядок сортировки. Синтаксис функции usort():

void usort(array массив, string имя_функции)

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

Листинг 5.2. Определение критерия сортировки для функции usort()

$vocab = аrrау( "Socrates", "Aristophanes", "Plato", "Aeschylus", "Thesmophoriazusae");
function compare_length($str1, $str2) {
    // Получить длину двух следующих слов
    $length1 = strlen($str1);
    $length2 = strlen($str2);
    // Определить, какая строка имеет меньшую длину
    if ($length1 == $length2) :
        return 0;
    elseif ($length1 < $length2) :
        return -1;
    else :
        return 1;
    endif;
}
// Вызвать usort() с указанием функции compare_length()
// в качестве критерия сортировки
usort ($vocab, "compare_length") :
// Вывести отсортированный список
while (list ($key, $val) = each ($vocab)) {
    echo "$val<br>";
}

В листинге 5.2 функция compare_length() определяет критерий сортировки массива. В данном случае это делается посредством сравнения длины передаваемых элементов. Функция-критерий должна получать два параметра, представляющих сравниваемые элементы массива. Также обратите внимание на то, как эти элементы неявно передаются функции-критерию при вызове usort(), и на то, что все элементы автоматически сравниваются этой функцией.

Функции uasort() и uksort() представляют собой разновидности usort() с тем же синтаксисом. Функция uasort() сортирует массив по пользовательскому критерию с сохранением ассоциаций «ключ/значение». Функция uksort() также сортирует массив по пользовательскому критерию, однако сортируются не значения, а ключи.

Другие полезные функции

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

array_merge()

Функция array_merge() сливает от 1 до N массивов, объединяя их в соответствии с порядком перечисления в параметрах. Синтаксис функции array_merge():

array array_merge(array массив1, array массив2, ..., array массивN)

Рассмотрим пример простого объединения массивов функцией array_merge();

$arr_1 = array("strawberry", "grape", "lemon");
$arr_2 = array("banana", "cocoa", "lime");
$arr_3 = array("peach", "orange");
$arr_4 = array_merge($arr_2, $arr_1, $arr_3);
// $arr_4 = array("banana", "cocoa", "lime", "strawberry", "grape", "lemon", "peach", "orange");

array_slice()

Функция array_slice() возвращает часть массива, начальная и конечная позиция которой определяется смещением от начала и необязательным параметром длины. Синтаксис функции array_slice():

array array_slice(array массив, int смещение [, int длина])

Значения параметров задаются по определенным правилам:

array_splice()

Функция array_splice() отдаленно напоминает array_slice() — она заменяет часть массива, определяемую начальной позицией и необязательной длиной, элементами необязательного параметра-массива. Синтаксис функции array_splice():

array_splice(array входной_массив, int смещение, [int длина], [array заменяющий_массив]);

Значения параметров задаются по определенным правилам:

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

Удаление всех элементов с пятой позиции до конца массива:

$pasta = array_splice($pasta, 5);

Удаление пятого и шестого элементов:

$pasta = array_splice($pasta, 5, 2);

Замена пятого и шестого элементов новыми значениями:

$pasta = array_splice($pasta, 5, 2, array("element1", "element2"));

Удаление всех элементов, начиная с пятого, до третьего элемента с конца массива:

$pasta = array_splice($pasta, 5, -3);

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

shuffle()

Функция shuffle() сортирует элементы массива в случайном порядке. Синтаксис функции shuffle():

void shuffle(array массив);

Итоги

В этой главе рассматривались массивы и стандартные функции РНР для работы с массивами. В частности, рассматривались следующие темы:

Массивы являются очень удобными и универсальными средствами для работы с данными в web-приложениях. В примерах дальнейших глав массивы будут неоднократно использоваться для повышения эффективности и наглядности кода.

В главе 6 мы продолжим знакомиться с базовыми средствами РНР. На этот раз речь пойдет об объектно-ориентированных возможностях языка.