Многомерные массивы
Это массив, который содержит массив внутри ячейки массива.
Пример
<?php
$auto["bmw"]=array("color"=>"белый", "year"=>"2005", "probeg"=>"2000");
$auto["audi"]=array("color"=>"синий", "year"=>"2003", "probeg"=>"2300");
Echo "<br> Год bmw - ".$auto["bmw"]["year"];
Echo "<br> Год audi - ".$auto["audi"]["year"];
?>
или
<?
$auto["bmw"]=array("color"=>"белый","year"=>"2005", "probeg"=>"2000");
$auto["audi"]=array("color"=>"синий", "year"=>"2003", "probeg"=>"2300");
Echo "<br> Год bmw - ".$auto["bmw"]["year"].".Цвет -".$auto["bmw"]["color"].".Пробег -".$auto["bmw"]["probeg"];
Echo "<br> Год audi - ".$auto["audi"]["year"];
?>
Инструкция list
Пример
$box=array ("Персик","Огурец");
List($fruit,$vegetable)=$box;
Echo"<br>$fruit<br>$vegetable";
Пусть у нас есть некоторый массив-список $List с тремя элементами: имя человека, его фамилия и возраст. Нужно присвоить переменным $name, $surname и $age эти величины. Это, можно сделать так:
$name=$List[0];
$surname=$List[1];
$age=$List[2];
Но если воспользоваться инструкцией list (), предназначенной как раз для таких целей, будет намного красивей и короче:
list($name,$surname,$age)=$List;
Инструкцию list можно задействовать для любого количества переменных: если в массиве не хватит элементов, чтобы их заполнить, им просто присвоятся неопределенные значения.
Если нам нужны только второй и третий элемент массива $List, то в таком случае имеет смысл пропустить первый параметр в инструкции list ():
list(,$surname,$age)=$List;
Получаем в $surname и $аgе фамилию и возраст человека, не обращая внимания на его имя в первом аргументе.
Замечание
Разумеется, можно пропускать любое число элементов, как слева или справа, так и посередине списка. Главное — не забыть проставить нужное количество запятых.
Следует сказать несколько слов насчет ассоциативных массивов языка РНР. Во-первых, на самом деле все "остальные" массивы также являются ассоциативными (в частности, списки — тоже). Во-вторых, ассоциативные массивы в РНР являются направленными, т. е. в них существует определенный (и предсказуемый) порядок элементов, не зависящий от реализации. А значит, есть первый и последний элементы, и для каждого элемента можно определить следующий за ним. Операция [ ] всегда добавляет элемент в конец массива, присваивая ему при этом такой числовой индекс, который бы не конфликтовал с уже имеющимися в массиве (точнее, выбирается номер, превосходящий все имеющиеся цифровые ключи в массиве). Вообще говоря, любая операция $Аггау[ключ]=значение всегда добавляет элемент в конец массива, конечно, за исключением тех случаев, когда ключ уже присутствует в массиве. Если вы захотите изменить порядок следования элементов в ассоциативном массиве, не изменяя в то же время их ключей, это можно сделать одним из двух способов: воспользоваться функциями сортировки, либо же создать новый пустой массив и заполнить его в нужном порядке, пройдясь по элементам исходного массива.
Функция isset и функция unset
Функция isset определяет существует ли переменная.
$z=isset($f) – если переменная $f существует то функция возвращает 1.
Используется совместно с инструкцией if.
If(isset($c)== "1")
{
Echo "переменная с существует и её значение : $c";
}
Else
{
Echo "переменная с не существует ";
{
функция unset – стирает переменную
пример
$v=10;
Unset($v);
echo "$v ";
Инструкция аггау() и многомерные массивы
Нам необходимо написать программу, которая по фамилии некоторого человека из группы будет выдавать его имя. Поступим так же, как и раньше: будем хранить данные в ассоциативном массиве (сразу отбрасывая возможность составить ее из огромного числа конструкций if-else как громоздкую):
$Names["Ivanov"] ="Dmitry";
$Names["Petrova"]="Vika" ;
Теперь можно, написать:
echo $Names["Petrova"]; // выведет Vika
echo $Names["Osipov"]; // ошибка: в массиве нет такого элемента!
Внимание: приведенный механизм никак не сможет создать пустой массив. Однако он очень часто может понадобиться, например, если мы не знаем, что раньше было в массиве $Names, но хотим его проинициализировать указанным путем. Кроме того, каждый раз задавать массив указанным выше образом не очень-то удобно — приходится все время однообразно повторять строку $Names...
Существует второй способ создания массивов, значительно более компактный. Это использование оператора array ( ) . Например:
// создает пустой массив $Names
$Names=array();
// создает такой же массив, как в предыдущем примере с именами
$Names=array("Ivanov"=>"Dmitry", "Petrova"=>"Helen");
// создает список с именами (нумерация 0,1,2}
$NamesList=array("Dmitry","Helen", "Sergey") ;
Формирование двумерных (и вообще многомерных) массивов. В самом деле, значениями переменных (и значениями элементов массива тоже, поскольку РНР не делает никаких различий между переменными и элементами массива) может быть все, что угодно, в частности — опять же массив. Так, можно создавать ассоциативные массивы (а можно — списки) с любым числом измерений. Например, если кроме имени о человеке известен также его возраст, то можно инициировать массив $Names так:
$Names["Ivanov"] = array("name"=>"Dmitry","age"=>25);
$Names["Petrova"] = array("name"=>"Helen", "age"=>23);
или даже так:
$Names=array{
"Ivanov" => array("name"=>"Dmitry","age"=>25) ,
"Petrova"=> array("name"=>"Helen", "age"=>23)
} ;
Чтобы добраться до нужного элемента в массиве:
echo $Names["Ivanov"]["age"]; // напечатает "25"
echo $Names["Petrova"]["bad"]; // ошибка: нет такого элемента "bad"
Можно видеть, что ассоциативные массивы в РНР удобно использовать как некие структуры, хранящие данные. Это единственный возможный способ организации структур, но он довольно гибок.
Операции над массивами
Существует довольно много операций, которые можно выполнять с массивами (в дополнение к общим операциям над переменными). Перечислим их, а заодно и подытожим все сказанное выше.
Доступ по ключу
Ассоциативные массивы — объекты, которые наиболее приспособлены для выборки из них данных путем указания нужного ключа. В РНР и для всех массивов, и для списков (которые, также являются массивами) используется один и тот же синтаксис, что является очень большим достоинством. Вот как это выглядит:
echo $Arr["anykey"]; // выводит элемент массива $Агг с ключом anykey
echo $Arr["first"]["second"]; // так используются двумерные массивы
echo (SomeFuncThatReturnsArrayO)[5];
// ОШИБКА! Так нельзя! А правильно будет:
$Arr= SomeFuncThatReturnsArray();
echo $Arr[5];
Последний пример показывает, что РНР сильно отличается от Си с точки зрения работы с массивами: в нем нет такого понятия, как "контекст массива", а значит, мы не можем применить [ ] непосредственно к значению, возвращенному функцией.
Величина $ Arr [КЛЮЧ] является полноценным "левым значением", т. е. может стоять в левой части оператора присваивания, от нее можно брать ссылку с помощью оператора &, и т. д. Например:
$Arr["anykey"]=array(100,200); // присваиваем элементу массива 100
$ref=&$Arr["first"]["second"]; // $ref — синоним элемента массива
$Arr[]="for add"; // добавляем новый элемент
Функция count()
Мы можем определить размер (число элементов) в массиве при помощи
стандартной функции count ():
$num=count($Names); // теперь в $num — число элементов в массиве
Отметим, что count ( ) работает не только с массивами, но и с объектами и даже с обычными переменными (для последних count () всегда равен 1, как будто переменная — это массив с одним элементом).
Пример.
$name[]="Александр";
$name[]="Иван";
$name[]="Аслан";
$h2=count($name);
Echo"<br> В массиве name найдено-$h2 элемента."
Слияние массивов
Еще одна фундаментальная операция — слияние массивов, т. е. создание массива, содержащего как элементы одного, так и другого массива. Реализуется это при помощи оператора +. Например:
$a=array("a"=>"aa", "b"=>"bb");
$b=array("c"=>"cc", "d"=>"dd");
$c=$a+$b;
В результате в $с окажется ассоциативный массив, содержащий все 4 элемента, а именно: array("a"=>"aa", "b"=>"bb", "c"=>"cc", "d"=>"dd"), причем именно в указанном порядке. Если бы мы написали $с=$b+$а, результат бы был немного другой, а именно: array ("c"=>"cc", "d"=>"dd", ;'а"=>"аа", "b"=>"bb"), т.е. элементы расположены в другом порядке.
То есть проявляется направленность массивов. Она заставляет оператор + стать некоммутативным, т. е. $а+$b не равно $b+$а, если $а и $b - массивы.
Следует быть особенно внимательным при слиянии таким образом списков.
Рассмотрим следующие операторы:
$а=аггау(10,20,30);
$b=array(100,200);
$с=$а+$b;
Вместо, $с будет аггау(10,20,30,100,200) на которое можно было бы рассчитывать, там окажется array(10,20,30). И вот почему так происходит. При конкатенации массивов с некоторыми одинаковыми элементами (то есть, элементами с одинаковыми ключами) в результирующем массиве останется только один элемент с таким же ключом — тот, который был в первом массиве, и на том же самом месте. Последний факт может слегка озадачить. Казалось бы, элементы массива $b по логике должны заменить элементы из $а. Однако все происходит наоборот. И еще следующий пример:
$а=аггау('а'=>10, 'Ь'=>20);
$b=array('Ь'=>'new? ' ) ;
$a+=$b;
Ожидается, что оператор += обновит элементы $а при помощи элементов $b. Но в результате этих операций значение $а не изменится*. Как же все-таки обновить элементы в массиве $а? Получается, только прямым способом — с помощью цикла (на самом деле, в РНР4 добавлена специальная функция array_merge (), лишенная указанного недостатка):
foreach ($b as $k=>$v) $a[$k]=$v;
Еще об операциях слияния массивов. Цепочка
$z=$a+$b+$c+...и т. д.;
эквивалентна
$z=$a; $z+=$b; $z+=$c; . . .и т. д.
Оператор += для массивов делает примерно то же, что и оператор += для чисел, а именно — добавляет в свой левый операнд элементы, перечисленные в правом операнде-массиве, если они еще не содержатся в массиве слева.
Итак, в массиве никогда не может быть двух элементов с одинаковыми ключами, потому что все операции, применимые к массивам, всегда контролируют, чтобы этого не произошло.
Внимание!
Так как списки являются тоже ассоциативными массивами, оператор + будет
работать с ними неправильно! Например, в результате слияния списков
аггау(10,20) и array(100,200, 300) получится список array(10,20, 300) —
всего из трех элементов!
Функция date
<? Php
$d=date("d-m-Y");
Echo"Сегодня:$d";
?>
Косвенный перебор элементов массива
Довольно часто при программировании на РНР приходится перебирать все без исключения элементы некоторого массива. Если массив — список, то эта задача, как мы уже знаем, не будет особенно обременительной:
// Пусть $Names — список имен. Распечатаем их в столбик
for($i=0; $i<count($Names); $i++)
echo $Names[$i]."br";
Везде, где можно, следует избегать помещения имени переменной-массива в кавычки — например, предыдущий пример:
for ($1=0; $i<count($Names); $i++)
echo "$Names[$i] ";
Дело в том, что это, единственный способ, который совместим с РНР версии 3. А что касается четвертой версии, то спокойно можно помещать массивы в строки, заключив их в фигурные скобки вместе с символом $:
$Names=array(
array('name'=>'Vika', 'age'=>20),
array ('name'=>'Kazbek', 'age'=>21)
);
for($i=0; $i<count($Names); $i++)
echo "($Names[$i] ['age'])";
Предположим, что массив $Names ассоциативный: его ключи — имена людей, а значения, сопоставленные ключам — например, возраст этих людей. Для перебора такого массива можно воспользоваться следующей конструкцией:
for(Reset($Names); ($k=key($Names)); Next($Names))
echo "Возраст $k — ($Names[$k]) лет ";
Эта конструкция опирается на еще одно свойство ассоциативных массивов в РНР. А именно, кроме того, что массивы являются направленными, в них есть еще и такое понятие, как текущий элемент. Функция Reset () просто устанавливает этот элемент на первую позицию в массиве. Функция key () возвращает ключ, который имеет текущий элемент (если он указывает на конец массива, возвращается пустая строка, что позволяет использовать вызов key () в контексте второго выражения for). Ну а функция Next () просто перемещает текущий элемент на одну позицию вперед.
На самом деле, две простейшие функции, — Reset ( ) и Next ( ), — помимо выполнения своей основной задачи, еще и возвращают некоторые значения, а именно:
функция Reset () возвращает значение первого элемента массива (или пустую строку, если массив пуст);
функция Next ( ) возвращает значение элемента, следующего за текущим (или пустую строку, если такого элемента нет).
Иногда бывает нужно перебрать массив с конца, а не с начала. Для этого воспользуйтесь такой конструкцией:
for(End($Names); ($k=key($Names)); Prev($Names))
echo "Возраст $k — ($Names[$k]) лет";
По контексту несложно сообразить, как это работает. Функция End ( ) устанавливает позицию текущего элемента в конец массива, a Prev ( ) передвигает ее на один элемент назад.
В РНР имеется функция current ( ) . Она очень напоминает key ( ), только возвращает не ключ, а величину текущего элемента (если он не указывает на конец массива).
Основное достоинство - "читабельность" и ясность кода, а также то, что массив мы можем перебрать как в одну, так и в другую сторону. Однако существуют и недостатки.
Вложенные циклы
Первый недостаток довольно фундаментален: мы не можем одновременно перебирать массив в двух вложенных циклах или функциях. Причина вполне очевидна: второй вложенный for "испортит" положение текущего элемента у первого for'a. К сожалению, эту проблему никак нельзя обойти (разве что сделать копию массива, и во внутреннем цикле работать с ней, но это не очень-то красиво). Однако практика показывает, что такие переборы встречаются крайне редко.
Нулевой ключ
А что, если в массиве встретится ключ 0 (хотя для массивов имен это, согласитесь, маловероятно)? Еще раз посмотрим на первый цикл перебора:
for(Reset($Names); ($k=key($Names)); Next($Names))
echo "Возраст $k – ($Names[$k]) лет";
В этом случае выражение ($k=key ($Names)), естественно, будет равно нулю, и цикл оборвется, чего бы совсем не хотелось.
Именно по этим причинам придуман другой, хотя и менее универсальный, но гораздо более удобный метод перебора массивов.
Прямой перебор массива
В отличие от косвенного перебора (когда сначала вычисляется очередной ключ, а уж затем по нему косвенно находится значение элемента массива), прямой перебор лаконичнее и гораздо более прост. Идея метода заключается в том, чтобы сразу на каждом "витке" цикла одновременно получать и ключ, и значение текущего элемента.
Классический перебор
Вернемся к примеру, в котором массив $Names хранил связь имен людей и их возрастов. Вот как можно перебрать этот массив при помощи прямого перебора:
for(Reset($Names); list($k,$v)=each($Names); /*пусто*/)
echo "Возраст $k — $v";
В самом начале заголовка цикла мы видим нашу знакомую функцию Reset ( ).
Дальше переменным $k и $v присваивается результат работы функции each (). Третье условие цикла попросту отсутствует (чтобы это подчеркнуть, на его месте комментарий).
Что делает функция each () ? Во-первых, возвращает небольшой массив (даже можно сказать, список), нулевой элемент которого хранит величину ключа текущего элемента массива $Names, а первый — значение текущего элемента. Во-вторых, она продвигает указатель текущего элемента к следующей позиции. Следует заметить, что если следующего элемента в массиве нет, то функция возвращает не список, a false. Именно поэтому она и размещена в условии цикла for. Становится ясно, почему мы не указали третий блок операторов в цикле for: он просто не нужен, ведь указатель на текущий элемент и так смещается функцией each ( ) .
Перебор в стиле РНР 4
Прямой перебор массивов применяется столь часто, что разработчики РНР в четвертой версии языка добавили специальную инструкцию перебора массива — foreach. Вот как с ее помощью можно перебрать и распечатать массив людей:
foreach($Names as $k=>$v) echo "Возраст $k — $v";
Этот способ перебора работает с максимально возможной скоростью — даже быстрее, чем перебор списка при помощи for и числового счетчика.
Замечание
Есть и еще одна причина предпочесть этот вид перебора "связке" цикла for с each(). Дело в том, что при применении foreach мы указываем имя перебираемого массива $Names только в одном месте, так что когда вдруг потребуется это имя изменить, нам достаточно будет поменять его только один раз. Наоборот, использование Reset () и each () заставит в таком случае изменить название переменной в двух местах, что потенциально может привести к ошибке. Представьте, что произойдет, если мы случайно изменим операнд each ( ) , но сохраним параметр Reset ( )!
Списки и строки
Есть несколько функций, которые чрезвычайно часто используются при программировании сценариев. Среди них — функции для разбиения какой-либо строки на более мелкие части (например, эти части разделяются в строке каким-то специфическим символом типа |), и, наоборот, слияния нескольких небольших строк в одну большую, причем не впритык, а вставляя между ними разделитель. Первую из этих возможностей реализует стандартная функция explode ( ) , а вторую — implode ( ) . Рекомендую обратить особое внимание на указанные функции, т. к. они применяются очень часто.
Функция explode ( ) имеет следующий синтаксис:
list explode(string $token, string $Str [, int $limit])
Она получает строку, заданную в ее втором аргументе, и пытается найти в ней подстроки, равные первому аргументу. Затем по месту вхождения этих подстрок строка "разрезается" на части, помещаемые в массив-список, который и возвращается. Если задан параметр $iimit, то учитываются только первые ($iimit-i) участков "разреза". Таким образом, возвращается список из не более чем $ limit элементов. Это позволяет нам проигнорировать возможное наличие разделителя в тексте последнего поля, если мы знаем, что всего полей, скажем, 6 штук. Вот пример:
$st="45972193611 Иванов|Иван|40|ivan@ivanov.com|Текст, содержащий (|) !";
$A=explode("I",$st,6); // Мы знаем, что там только 6 полей!
// теперь $А[0]="Иванов", ... $А[5]= "Текст, содержащий (I)!"
list($Surname,$Name,$Age,$Email,$Tel)=$A; // распределили по переменным
Конечно, строкой разбиения может быть не только один символ, но и небольшая строка. Не перепутать только порядок следования аргументов при вызове функции!
Функция implode () и ее синоним join () производят действие, в точности обратное вызову explode ( ) .
string implode(string $glue, list $List) или
string join(string $glue, list $List)
Они берут ассоциативный массив (обычно это список) $List, заданный в ее первом параметре, и "склеивают" его значения при помощи "строки-клея" $glue во втором параметре. Примечательно, что вместо списка во втором аргументе можно передавать любой ассоциативный массив — в этом случае будут рассматриваться только его значения.
Рекомендуется применять функции implode () и explode (), ибо они работают очень быстро.