Динамическое формирование массивов

ЛАБОРАТОРНАЯ РАБОТА

Тема: Работа с массивами

Цель работы: Освоить характерные для РНР приемы работы с массивами

Общая информация о массивах РНР приведена в справочном разделе.

Создание массивов с помощью функции-конструктора

В РНР определена функция-конструктор array, которая возвращает созданный объект массива. С ее помощью можно создавать инициализированные и неинициализированные массивы.

а) Создание неинициализированного массива.

$arr1 = array();

б) Создание и инициализация скалярного (пронумерованного) массива.

$arr2= array("http://www.yandex.com",

"http://www.google.com",

"http://www.altavista.com");

В этом случае РНР присваивает по умолчанию значениям числовые значения ключей, начиная с нуля.

в) Создание и инициализация ассоциативного массива.

При создании ассоциативного массива значения ключей необходимо указывать явно. В следующем примере формируется массив из трех значений с ключами "yandex", "google", "altavista". В РНР для установления ассоциации используется оператор =>

$arr3=array("yandex"=>"http://www.yandex.com",

"google"=>"http://www.google.com",

"bing"=>"http://www.altavista.com");

ЗАДАНИЕ 1 (Простейший анализ массивов)

1. Для каждого из приведенных определений массивов ($arr1, $arr2, $arr3)

а) получить и вывести длину массива,

б) получить и вывести массивы ключей и значений; для вывода использовать цикл for, полученную информацию представить строками

ключ=…. значение=…

в) используя функции print_r и var_dump вывести информацию о массивах в отладочном формате; выяснить различие в форматах выводимой этими функциями информации.

2. Применить функции print_r и var_dump для массива, в котором один из элементов также является массивом.

$arr4 = array(1,"asd",array(2,3));

3. Создать в скрипте простую переменную и присвоить ей целочисленное значение. Применить к этой переменные функции print_r и var_dump.

4. Проанализировать результаты примеры 1-3, сформулировать, в чем состоит основное различие между функции print_r и var_dump.

Примечание.

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

$arr5=array(0=>"http://www.yandex.com",

1=>"http://www.google.com",

"2"=>"http://www.altavista.com");

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

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

$arr6=array(2=>"http://www.yandex.com",

4=>"http://www.google.com",

1=>"http://www.altavista.com");

Однако, в зависимости от способа просмотра, при выводе элементов такой массив может выглядеть по-разному.

Оператор foreach

Для скалярных массивов задача перебора всех элементов массива решается с помощью последовательного назначения индексов оператором for. Однако для ассоциативных массивов, где индексы или строки, или числа, но не подряд, этот оператор неприменим.

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

foreach($arr as [$key =>] $val) {

… }

(в квадратные скобки, как обычно, взят необязательный элемент конструкции).

Здесь

$arr — имя массива,

$val — переменная, через которую при итерации будут возвращаться поочередно значения текущих элементов, а через переменную

$key — ключи текущих элементов.

Оператор удобно применять даже к обычным скалярным массивам. Например, массив может быть индексирован числами, но точное число элементов неизвестно. Чтобы обработать массив обычным образом с помощью for, необходимо сначала вычислить количество элементов в массиве (функции count или sizeof), а затем выполнить цикл for. Оператор foreach позволяет выполнить это "в одно действие".

ЗАДАНИЕ 2 (Использование оператора foreach)

1. С помощью оператора foreach в полной форме

foreach($arr as $key=>$val)

вывести в виде таблицы с двумя колонками "ключ/значение" элементы массивов $arr5 и $arr6, и сравнить результаты с определением массивов.

2. Использовать для одного из массивов сокращенную форму

foreach($arr as $x)

и выяснить, что возвращается через переменную $x в этом случае.

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

$arr[3]="Четвертый";

$arr[0]="Первый";

. . .

Вывести значения этого массива двумя способами:

а) с помощью оператора for (в сочетании с count() или sizeof()),

б) с помощью оператора foreach.

Есть ли различие в работе операторов и какое?

Динамическое формирование массивов

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

$arr7["yandex"]="http://www.yandex.com";

$arr7["google"]="http://www.google.com";

$arr7["altavista"]="http://www.altavista.com";

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

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

$arr8[]="http://www.yandex.com";

$arr8[]="http://www.google.com";

$arr8[]="http://www.altavista.com";

Замечание.

Чтобы "назначить какому-то элементу числовое значение ключа", то интерпретатор "наращивает" значения ключей, начиная с указанного. Т.е., если бы в первой строке предыдущего примера было бы записано

$arr8[2]="http://www.yandex.com";

то второй и третий элементы получили бы значения ключей 3 и 4 соответственно.

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

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

Рассмотрим случай двумерного массива. Концептуально двумерный массив — это одномерный массив одномерных массивов. На этом построены и методы конструирования двумерных массивов.

а) Использование функций-конструкторов.

$usefulSites=array(

array("http://www.yandex.com","http://www.google.com",

"http://www.altavista.com"),

array("http://www.php.com","http://www.rusdoc.ru")

);

или (после определения массивов $searchEngines и $phpDocs)

$searchEngines=array("http://www.yandex.com",

"http://www.google.com",

"http://www.altavista.com");

$phpDocs= array("http://www.php.com",

"http://www.rusdoc.ru");

можно поступить проще

$usefulSites=array($searchEngines, $phpDocs);

Для обращения к двумерным массивам используется синтаксис, принятый в Си.

ЗАДАНИЕ 3(Работа с многомерными массивами)

1. Используя циклы foreach вывести значения элементов двумерного массива $usefulSites построчно.

Итератор each

Для последовательного просмотра элементов массива можно применять итератор each. Его работа основана поддержке каждым массивом внутреннего указателя. Этот указатель ссылается на текущий (current) элемент, который будет обработан при очередном вызове итератора. После определения массива текущим назначается первый элемент массива.

При каждом обращении функция each извлекает из массива информацию о текущем элементе и автоматически сдвигает внутренний указатель на следующий элемент. Когда внутренний указатель достигает конца массива, то each возвращает false.

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

Для непосредственной работы с внутренним указателем массива предлагается пять функций: current, prev, next, end, reset (см. справочную информацию).

ЗАДАНИЕ 4 (Итерация по массиву)

Используя цикл

while($x=each($arr7)){…}

вывести информацию об элементах массива $arr7, получаемую в переменной $x. Для вывода использовать функцию print_r , а информацию о каждом элементе выводить в отдельной строке.

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

Конструкция list

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

Однако синтаксис использования list необычен: конструкция помещается в левую часть оператора '=' и ей "присваивается" массив. Этот массив должен иметь элементы с числовыми индексами.

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

Т.е. первому своему аргументу конструкция присваивает значение первого элемента массива, второму — второго и т.д., пока не исчерпается список аргументов. Позиции в списке можно пропускать, добавляя лишнюю запятую.

Пример

$a=array(0=>1,2=>2);

list($x,,$y)=$a;

print $y; //2

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

Если список аргументов list длиннее, чем массив, то возникает ошибка Undefined offset:...

Работа конструкции list не связана с положением внутреннего указателя массива.

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

Так как итератор each возвращает информацию, в том числе, и в элементах с числовыми индексами, то list часто применяется вместе с итератором, чтобы сразу скопировать ключ и значение элемента в простые переменные.

ЗАДАНИЕ 5(Использование конструкции list)

1. В условиях предыдущего задания, используя вместо переменной $x конструкцию list($key,$value), вывести в цикле на экран пары "ключ/значения" в формате

ключ => значение

Замечание

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

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

Справочная информация

Наши рекомендации