PHP5_nachinayushim
.pdf204 Глава 4
Теперь, если в массив добавить следующую строку:
$director[]="Alfred Hitchcock";
то строка Alfred Hitchcock будет помещена в массив и получит индекс 94, а не 0, потому что наибольшим значением используемых индексных чисел является 93,
иPHP назначит следующему незаполненному элементу индекс 94. Как можно опреде+ лить, какой индекс будет назначен новому элементу при условии, что функции key()
иcurrent() возвращают информацию по тому элементу, который был помещен в массив первым? Ответ на этот вопрос дан в следующем разделе.
Функции next() и prev()
Для определения индексного значения нового элемента, добавленного в массив, используются функции next() и prev(). Они позволяют перемещаться по массивам, передвигая указатель на следующий или предыдущий элемент соответственно. В качест+ ве аргумента обе функции принимают имя массива. Например, для созданного в пре+ дыдущем примере массива:
$director[4]="Orson Welles";
$director[1]="Carol Reed";
$director[93]="Fritz Lang";
$director[24]="Jacques Tourneur";
$director[]="Alfred Hitchcock";
можно вызвать функцию next() до проверки текущего индекса и содержимого текущего элемента:
next($director);
$current_index_value = key($director); echo ($current_index_value);
В результате этого будет отображено значение 1, а функция current() вернет строку Carol Reed.
Если вызвать функцию next() еще три раза
next($director); next($director); next($director); next($director);
$current_index_value = key($director); echo ($current_index_value);
будет выведено значение 94. Если теперь вызвать функцию current():
$current_contents = current($director); echo ($current_contents);
то в браузере будет выведена строка ‘‘Alfred Hitchcock’’.
Функция prev() используется аналогично. Возьмем предыдущий пример и доба+ вим вызов prev() после четырех вызовов next():
next($director); next($director); next($director); next($director); prev($director);
$current_index_value = key($director); echo ($current_index_value);
Ввиду того, что указатель был передвинут вперед на четыре элемента и на один на+ зад, будет выведено число 24, которое является индексным значением, связанным со строкой Jacques Tourneur. Это довольно просто, хотя возникает один вопрос: что
Логические операторы, циклы и массивы 205
случится, если вызов next() передвинет указатель за последний элемент массива или prev() установит указатель перед первым элементом?
prev($director);
$current_index_value = key($director); echo ($current_index_value);
Ничего особенного не произойдет. Код не вернет никакого значения и не сгене+ рирует ошибку (как это было бы в некоторых языках программирования); указатель просто выходит за границу массива, но его можно вернуть обратно:
prev($director); next($director); next($director);
$current_index_value = key($director); echo ($current_index_value);
В данном случае также не будет никакого вывода.
Итак, очевидно, что порядок, в котором наполняется массив, никак не влияет на порядок перемещения по элементам массива. Любое новое значение, добавленное в массив, помещается в элемент, который следует сразу за существующим элементом, имеющим наибольший индекс. Поэтому если наивысший индекс заполненного эле+ мента равен 34, то следующее значение будет вставлено в массив с индексом 35.
Следует запомнить, что для перемещения по массиву используются функции next() и prev(), а для отображения текущей позиции (элемента, на который в текущий мо+ мент времени ссылается указатель) используются функции current() и key().
Функции list() и each()
Можно упростить перемещение в неупорядоченных массивах. Вместо того чтобы обрабатывать в цикле множество пустых значений, можно использовать функции list() и each(), и возвращать только те элементы массива, которые содержат дан+ ные. Это позволяет с минимальными усилиями отображать все содержимое массива. Для этого используется цикл while:
while (list(IndexValue,ElementContents) = each(ArrayName))
Это означает: для каждого элемента массива ArrayName установить значение IndexValue равным индексу элемента, а значение ElementContents равным содержимому данного элемента. Если требуется возвращать либо индекс, либо значение, то лишний атрибут можно просто опустить:
while (list(IndexValue) = each(ArrayName))
или
while (list(,ElementContents) = each(ArrayName))
Для отображения имени каждого режиссера можно написать следующий код:
while (list($element_index_value, $element_contents) = each($director)){ echo "<br>$element_index_value - $element_contents";
}
Называть переменные именами $element_index_value и $element_contents
необязательно; это сделано просто для ясности. Их можно было бы назвать по+другому:
while (list($MickeyMouse, $DonaldDuck) = each ($Director)){ echo "<BR>$MickeyMouse - $DonaldDuck";
}
206 Глава 4
В любом случае результат будет следующим:
4 - Orson Welles
1 - Carol Reed
93 - Fritz Lang
24 - Jacques Tourneur
94 - Alfred Hitchcock
Необходимо помнить только то, что функция list() возвращает сначала индекс, а затем содержимое элемента. Это предоставляет программисту некоторые полезные средства, которые применимы даже тогда, когда массив не имеет числовых индексов.
Итерации в ассоциативных массивах
Для перемещения по элементам ассоциативных массивов характерны те же пра+ вила, что и для массивов с числовыми индексами, однако имеются небольшие отли+ чия. Во+первых, следующие строки, которые хорошо работали бы, если бы массив был численно индексированным, теперь создают ассоциативный массив:
$state_capital["GA"]="Atlanta"; $state_capital["IL"]="Springfield"; $state_capital["CA"]="Sacramento"; $state_capital[] = "Cheyenne";
Значение Cheyenne будет сохранено в элементе $state_capital[0]. Это не уди+ вительно, учитывая, что PHP ‘‘не знает’’, какие индексные значения намерен исполь+ зовать программист; это может быть WY или AB, или 4563, поэтому PHP пытается най+ ти наибольший числовой индекс. Поскольку при создании массива числовые индексы не добавлялись, PHP начинает с нуля.
Функции current() и key() будут работать так, как и предполагается для ассо+ циативных массивов. Следующий код
$what_state = current($state_capital); $what_abbreviation = key($state_capital); echo "$what_abbreviation - $what_state";
вернет первый элемент массива, т.е. элемент с индексом GA, содержащий значение Atlanta. Можно перемещаться по элементам массива, как и раньше:
$state_capital["GA"]="Atlanta"; $state_capital["IL"]="Springfield"; $state_capital["CA"]="Sacramento"; $state_capital[] = "Cheyenne"; next($$state_capital);
$what_state = current($state_capital); $what_abbreviation = key($state_capital); echo "$what_abbreviation - $what_state";
На этот раз отображается результат IL - Springfield. Функции list() и each() тоже работают. Можно создать следующий массив:
$state_capital = array ("GA" => "Atlanta", "IL" => "Springfield", "CA" => "Sacramento", "WY" => "Cheyenne");
А затем передавать данный массив функции each и использовать list() для ото+ бражения содержимого элементов:
while (list($state_abbreviation, $state_name) = each ($state_capital)){ echo "<br>$state_abbreviation - $state_name";
}
При этом, как и ожидалось, создается список аббревиатур и названий штатов, а за+ тем они отображаются в том порядке, в котором были созданы:
Логические операторы, циклы и массивы 207
GA - Atlanta
IL - Springfield
CA - Sacramento
WY - Cheyenne
Как заставить PHP создать или сохранить другой порядок? Читайте об этом в сле+ дующем разделе.
Сортировка массивов
В PHP имеется несколько функций для сортировки массивов. В данном разделе рассматриваются пять наиболее широко используемых функций: sort(), asort(), rsort(), arsort() и ksort(). Все они работают совместно с уже рассмотренными функциями list() и each().
Функция sort()
sort() ++++++ основная функция сортировки. Она принимает элементы массива и сортирует их в алфавитном порядке. Функции требуется передать только имя сор+ тируемого массива:
sort(ArrayName)
Если массив режиссеров создается с помощью функции array():
$director = array ("Orson Welles","Carol Reed","Fritz Lang","Jacques Tourneur");
то можно отсортировать элементы, передав функции sort() имя данного массива:
sort($director);
Чтобы понять, как данная функция влияет на массив, можно снова использовать функции list() и each(). Как уже отмечалось, в массиве элементы хранятся в том порядке, в котором они были созданы. В данном массиве ожидается следующий поря+ док элементов:
$director[0]= "Orson Welles"
$director[1]= "Carol Reed"
$director[2]= "Fritz Lang"
$director[3]= "Jacques Tourneur"
Однако после использования функции sort() порядок будет другим, так как функция расположила значения элементов в алфавитном порядке, а затем пере+ строила индексные номера так, чтобы они соответствовали новому порядку:
$director[0]= "Carol Reed"
$director[1]= "Fritz Lang"
$director[2]= "Jacques Tourneur"
$director[3]= "Orson Welles"
Это можно проверить, воспользовавшись ранее созданным фрагментом кода, ко+ торый отображает на экране содержимое списка:
while (list($IndexValue, $DirectorName) = each ($director)){ echo "<BR>$IndexValue - $DirectorName";
}
Функция asort()
Функция asort() принимает массивы со строковыми индексами и сортирует их согласно значениям элементов. Это не совсем то же самое, что делает функция sort. asort() ++++++ оставляет индексные номера или имена элементов нетронутыми, а не пе+ рестраивает их, как функция sort. Обратимся снова к массиву столиц штатов:
208 Глава 4
$state_capital = array ("GA" => "Atlanta", "IL" => "Springfield", "CA" => "Sacramento", "WY" => "Cheyenne");
Массив создается так же, как и при использовании следующего кода:
$state_capital["GA"]= "Atlanta" $state_capital["IL"]= "Springfield" $state_capital["CA"]= "Sacramento" $state_capital["WY"]= "Cheyenne"
Вызовем для данного массива функцию sort():
sort($state_capital);
В результате этого образуется следующий порядок:
$state_capital[0]= "Atlanta" $state_capital[1]= "Cheyenne"
$state_capital[2]= "Sacramento" $state_capital[3]= "Springfield"
Иными словами, строковые индексы были заменены числовыми индексами, что не очень полезно. Но если вместо этого вызывать функцию asort():
asort($state_capital);
то порядок будет таким:
$state_capital["GA"]= "Atlanta" $state_capital["WY"]= "Cheyenne" $state_capital["IL"]= "Sacramento" $state_capital["CA"]= "Springfield"
На этот раз элементы были отсортированы в алфавитном порядке, а строковые индексы остались. Чтобы убедиться, что это действительно так, можно снова исполь+ зовать функции list() и each():
while (list($state_abbreviation, $state_name) = each ($state_capital)){ echo "<br>$state_abbreviation - $state_name";
}
Функции rsort() и arsort()
Функции rsort() и arsort() работают аналогично своим близким родственникам sort() и asort(). Единственным отличием является то, что они возвращают элемен+ ты в обратном алфавитном порядке. Для того чтобы отсортировать список режиссеров в обратном алфавитном порядке, можно использовать функцию rsort():
$director = array ("Orson Welles","Carol Reed","Fritz Lang","Jacques Tourneur");
rsort($director);
Для сортировки списка столиц штатов можно использовать функцию arsort():
$state_capital = array ("ga" => "Atlanta", "il" => "Springfield", "ca" => "Sacramento", "wy" => "Cheyenne");
arsort($state_capital);
Результаты должны быть очевидны. Чтобы проверить их, можно адаптировать код для отображения результатов из предыдущих разделов. Данные функции полезны, ес+ ли требуется отсортировать элементы по убыванию, а не по возрастанию.
Логические операторы, циклы и массивы 209
Функция ksort()
Функция ksort() сортирует содержимое ассоциативного массива по индексам. Она применяется точно так же, как другие функции сортировки, но упорядочивает ассоциативный массив в алфавитном порядке строковых индексов. Эта функция по+ лезна для сортировки по индексным номерам или именам элементов, когда необхо+ димо манипулировать данными по именам элементов, а не по значениям. Например, в случае списка столиц штатов:
$state_capital = array ("ga" => "Atlanta", "il" => "Springfield", "ca" => "Sacramento", "wy" => "Cheyenne");
ksort($state_capital);
функция ksort() создаст следующий порядок:
$state_capital["ca"]= "Sacramento" $state_capital["ga"]= "Atlanta" $state_capital["il"]= "Springfield" $state_capital["wy"]= "Cheyenne"
Поэтому если для каких+либо целей понадобится использовать аббревиатуры шта+ тов, а не их названия, то их также можно отсортировать.
Многомерные массивы
PHP позволяет создавать массивы массивов. Такие структуры получили название многомерных массивов. Они полезны для представления данных, которые требуют двух наборов индексов, например, координат на карте. В принципе, существует воз+ можность создавать вложенные массивы в многомерном массиве до тех пор, пока PHP будет хватать памяти. Вероятно, этот предел наступает в районе 100 вложенных мас+ сивов (тот, кто сможет предложить целесообразное практическое применение для массивов с более чем 10 вложенными массивами, заслуживает особой награды). Мно+ гомерные массивы создаются так же, как и обычные массивы, за исключением того, что конструкция array вызывается как аргумент для самой себя:
ArrayName = array (index => array (элементы массива))
В качестве примера можно описать массив, в котором каждый элемент представ+ ляет одного члена какой+либо группы людей и одновременно является массивом, со+ держащим некоторые сведения об этом человеке:
$phone_directory = array ("John Doe" => array ("1 Long Firs Drive", "777-000-000"), "Jane Doe" => array ("4 8th and East","777-111-111"));
В данном массиве содержатся элементы John Doe и Jane Doe; и каждый из этих элементов в свою очередь представляет массив с двумя элементами: адресом и номе+ ром телефона. Чтобы распечатать данную информацию, необходимо использовать вложенный цикл:
$phone_directory = array ("John Doe" => array("1 Long Firs Drive", "777-000-000"),
"Jane Doe" => array("4 8th and East","777-111-111")); while (list($person) = each($phone_directory)){
echo("<br>$person");
while (list(,$personal_details) = each ($phone_directory[$person])) { echo (" $personal_details");
}
}
Тег <br> и пробел перед $personal_details в операторе echo используются просто для того, чтобы сделать вывод информации удобочитаемым. Многомерные массивы встречаются не очень часто, поэтому здесь они не описываются.
210 Глава 4
Практическое использование массивов
Материал данной главы проиллюстрирован на кратком примере, который вклю+ чает многие из рассмотренных функций.
Практика Комбинированное использование функций для работы с массивами
В следующем примере группе вымышленных студентов предлагается ответить на вопросы об оценках, которые они получили на экзамене по математике. Кроме все+ го прочего на Web+странице имена студентов будут отсортированы в порядке полу+ ченных студентами оценок (A ++++++ самая высокая оценка, F ++++++ самая низкая). Чтобы представить результаты в более читабельном виде, используется несколько HTML+ таблиц (теги <table>).
1. Запустите редактор Web+страниц и введите следующий код:
<html>
<head><title></title></head>
<body>
<form method="POST" action="exam.php">
<input type="hidden" name="posted" value="true"> <table border="1">
<?php
$student = array("Альберт Эйнштейн","Иван Грозный","Наполеон","Саймон Боливар","Исаак Ньютон");
while (list(,$name) = each($student))
{
echo "<tr><td>Какую оценку по математике получил <b>$name</b>?</td>"; echo"<td><select name='math[]'>
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
<option>F</option>
</select>";
echo"<input type='hidden' name='student[]' value='$name'></td>";
}
?>
</tr>
<tr><td> </td><td>
<input type="submit" value="Показать оценки"> </td></tr>
</form>
</table>
<?php
if (isset($_POST['posted'])) { ?>
<hr>
<table border="1">
<tr><td colspan="2">
Оценки по математике расположены в следующем порядке: </td></tr>
<?php
while (list($index,$value)=each($_POST['math']))
{
$gradestudent[]=$_POST['math'][$index].$_POST['student'][$index];
}
Логические операторы, циклы и массивы 211
asort($gradestudent);
while (list($index,$value)=each($gradestudent))
{
$student_index = $_POST['student'][$index]; $math_index = $_POST['math'][$index];
echo "<tr><td><b>$student_index</b></td><td>$math_index</td></tr>";
}
}
?>
</table>
</body>
</html>
2.Сохраните данный файл как exam.php и закройте его.
3.Откройте созданный файл в браузере и введите несколько оценок (пример на рис. 4.12).
Рис. 4.12.
4.Нажмите кнопку Показать оценки и данные будут отсортированы не только по оценкам, но и в алфавитном порядке имен студентов, если несколько студентов получили одинаковые оценки (рис. 4.13).
212 Глава 4
Рис. 4.13.
Как это работает
Представленная программа решает сложную задачу по сортировке полученных дан+ ных. Необходимо отсортировать массив оценок, которые согласованы по индексу с мас+ сивом студентов. Однако как можно связать отсортированный массив оценок с масси+ вом студентов? Сделать это без особых сложностей позволяет один технический прием.
Программа создает динамическую форму, которая выводит имена студентов из массива $student:
<form method="POST" action="exam.php">
<input type="hidden" name="posted" value="true"> <table border="1">
<?php
$student = array("Альберт Эйнштейн","Иван Грозный","Наполеон","Саймон Боливар","Исаак Ньютон");
Цикл while обрабатывает элементы данного массива. Понадобятся только имена сту+ дентов, а не их индексы, поэтому функции list() передается только второй параметр:
while (list(,$name) = each($student))
{
Для всех студентов в списке отображаются запросы оценок:
echo "<tr><td>Какую оценку по математике получил <b>$name</b>?</td>";
Логические операторы, циклы и массивы 213
Затем создается выпадающий список, содержащий пять пунктов, соответствующих пяти оценкам от A до F. Для хранения оценок создается массив $math, который PHP сможет передать следующему сценарию:
echo"<td><select name='math[]'> <option>A</option> <option>B</option> <option>C</option> <option>D</option> <option>F</option>
</select>";
Значение для второй части сценария передается через скрытое поле формы, кото+ рое имеет то же имя, что и массив с именами студентов. Чтобы указать, что данный эле+ мент управления должен быть массивом, к его имени добавляются квадратные скобки. Для каждого студента передается имя элемента управления, а затем цикл завершается:
echo"<input type='hidden' name='student[]' value='$name'></td>";
}
После цикла вставляется кнопка отправки запроса и форма закрывается:
?>
</tr>
<tr><td> </td><td>
<input type="submit" value="Показать оценки"> </td></tr>
</form>
</table>
Вторая часть программы получает данные из формы. Эта часть состоит из цикла, сортировки и еще одного цикла.
Первый цикл используется для связи двух массивов, полученных из формы. Это делается путем конкатенации оценки и имени студента и сохранения результата в но+ вом массиве $gradestudent:
<hr>
<table border="1">
<tr><td colspan="2">
Оценки по математике расположены в следующем порядке: </td></tr>
<?php
while (list($index,$value)=each($_POST['math']))
{
$gradestudent[]=$_POST['math'][$index].$_POST['student'][$index];
}
Из кода первой части сценария известно, что значение элемента с определенным индексом в массиве $math связано со значением элемента с таким же индексом в мас+ сиве $student. Поэтому конкатенация представляет собой верный способ объедине+ ния связанных значений из каждого массива. Результирующий массив $gradestudent содержит следующие данные:
CАльберт Эйнштейн FИван Грозный BНаполеон DСаймон Боливар AИсаак Ньютон
Теперь необходимо соответствующим образом отсортировать массив $gradestudent:
asort($gradestudent);