Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка PHP 2008.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
1 Мб
Скачать
☆

Тема 5 Ассоциативные массивы

5.1 Списки и ассоциативные массивы

5.2 Операции над массивами

5.3 Списки и строки

5.4 Сериализация

5.1 Списки и ассоциативные массивы

Особенности ассоциативных массивов:

1. Все массивы PHP являются ассоциативными (в частности, списки – тоже).

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

3. Операция [] всегда добавляет элемент в конец массива, присваивая ему при этом такой числовой индекс, который бы не конфликтовал с уже имеющимися массиве (выбирается номер, превосходящий все имеющиеся цифровые ключи в массиве).

4. Операция $Array[ключ]=значение добавляет элемент в конец массива, за исключением тех случаев, когда ключ уже присутствует в массиве.

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

5.2 Операции над массивами

Над массивами можно выполнять следующие операции:

Инициализация массива.

$NamesList[0]="Dmitry";

$NamesList[l]="Helen";

$NamesList [2]="Sergey";

Печать элементов массива. Количество элементов в массиве легко можно определить функцией count() или ее синонимом sizeof():

for($i=0; $i<count($NamesList); $i++)

echo $NamesList[$i]."<br>";

Добавление элементов в массив (создание массива «на лету»). Автомассивы. Для добавления элемента в конец массива можно не задавать номер элемента массива.

$NamesList[]="Dmitry";

$NamesList[]="Helen";

$NamesList[]="Sergey";

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

Ассоциативный массив часто называется просто хэш.

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

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

$Names["Koteroff"]="Dmitry";

$Names["Ivanov"]="Ivan";

$Names["Petrov"]="Peter";

Имя любого абонента можно распечатать командой:

echo $Names["Ivanov"] ;

$f="Koteroff";

echo $Names[$f];

Инструкция list(). Пусть есть некоторый массив-список $List с тремя элементами: имя человека, его фамилия и возраст. Нужно присвоить переменным $name, $surname и $age эти величины. Это можно сделать следующим образом:

$name=$List[0];

$surname=$List[1] ;

$age=$List[2];

Однако лучше воспользоваться инструкцией list():

list($name, $surname, $age)=$List;

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

list(,$surname,$age)=$List;

Можно пропускать любое число элементов, как слева или справа, так и посередине списка. Главное – не забыть проставить нужное количество запятых.

Инструкция аrrау() и многомерные массивы. Пусть необходимо написать программу, которая по фамилии некоторого человека из группы будет выдавать его имя. Данные хранятся в ассоциативном массиве:

$Names["Ivanov"]="Dmitry";

$Names ["Petrova"]="Helen";

Теперь можно написать:

echo $Names["Petrova"]; // выведет Helen

echo $Names["Oshibkov"]; // ошибка: в массиве нет такого

// элемента!

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

Второй способ создания массивов – это использование оператора 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=аrraу(

"Ivanov"=>array("name"=>"Dmitry","age"=>25) ,

"Petrova"=>array("name"=>"Helen","age"=>23));

Получить нужный элемента массиве можно следующим образом:

echo $Names["Ivanov"]["age"]; // напечатает "25"

echo $Names["Petrova"]["bad"]; // ошибка: нет такого

// элемента "bad"

Ассоциативные массивы в РНР удобно использовать как некие структуры, хранящие данные. Это похоже на конструкцию struct в Си (или record в Паскале). Это единственный возможный способ организации структур, но он очень гибок.

Доступ по ключу.

//выводит элемент массива $Аrr с ключом anykey

echo $Arr ["anykey"];

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

echo $Arr ["first"]["second"];

echo $Arr[5];

Величина $Arr[ключ] является полноценным «левым значением», т. е. может стоять в левой части оператора присваивания, от нее можно брать ссылку с помощью оператора &, например:

//присваиваем элементу массива 100

$Arr["anykey"]=array(100,200);

//$ref – синоним элемента массива

$ref=&$Arr["first"]["second"];

$Arr[]="for add"; // добавляем новый элемент

Функция соunt() – определяет число элементов массива:

$num=count($Names); // $num – число элементов в массиве

Слияние массивов, т.е. создание массива, содержащего как элементы одного, так и другого массива. Реализуется при помощи оператора +. Например:

$а=аrrау("а"=>"аа", "b"=>"bb") ;

$b=array("c"=>"cc", "d"=>"dd");

$c=$a+$b;

В результате в $с окажется ассоциативный массив, содержащий все 4 элемента:

array("a"=>"aa","b"=>"bb","c"=>"cc","d"=>"dd"),

причем именно в указанном порядке.

Направленность массивов заставляет оператор + стать некоммутативным, т. е. $а+$b не равно $b+$а, если $а и $b массивы.

Так как списки являются тоже ассоциативными массивами, оператор + будет работать с ними неправильно! При слиянии списков:

$а=аrrау(10,20,30);

$b=array(100,200);

$c=$a+$b;

в $с будет array(10,20,30) !

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

При слиянии ассоциативных массивов

$а=аrraу("а"=>10, "b"=>20);

$b=array("b"=>"new?");

$a+=$b;

оператор += не обновит элементы $а при помощи элементов $b. В результате этих операций значение $а не изменится.

Обновить элементы в массиве $а можно с помощью цикла:

foreach ($b as $k=>$v) $a[$k]=$v;

Цепочка

$z=$a+$b+$c+ ...

эквивалентна

$z=$a; $z+=$b; $z+=$c; ...и т. д.

Оператор += для массивов добавляет в свой левый операнд элементы, перечисленные в правом операнде-массиве, если они еще не содержатся в массиве слева.

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

Косвенный перебор элементов массива. Используется для перебора всех элементов массива.

Если массив – список:

//Пусть $Namеs – список имен. Распечатаем их в столбик

for($i=0; $i<count ($Names); $i++)

echo $Names[$i]."\n";

Переменную можно помещать в строку:

for ($i=0; $i<count($Names); $i++)

echo "$Names[$i]\n";

Можно помещать массивы в строки, заключив их в фигурные скобки вместе с символом $:

$Names=array(array('name'=>'Вася','age'=>20),

array('name'=>'Билл','аgе'=>40));

for ($i=0; $i<count($Names); $i++)

echo "{$Names[$i]['age']}\n";

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

for(Reset($Names);($k=key($Names));Next($Names))

echo "Возраст $k – {$Names[$k]} лет\n";

Кроме того, что массивы являются направленными, в них есть еще и такое понятие, как текущий элемент. Функция Reset() устанавливает этот элемент на первую позицию в массиве. Функция key() возвращает ключ, который имеет текущий элемент (если он указывает на конец массива, возвращается пустая строка, что позволяет использовать вызов key() в контексте второго выражения for), а функция Next() перемещает текущий элемент на одну позицию вперед.

Функции Reset() и Next() возвращают следующие значения:

– функция Reset() возвращает значение первого элемента массива (или пустую строку, если массив пуст);

– функция Next() возвращает значение элемента, следующего за текущим (или пустую строку, если такого элемента нет).

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

for(End($Names);($k=key($Names));Prev($Names))

echo "Возраст $k – {$Names[$k]} лет\n";

Функция End() устанавливает позицию текущего элемента в конец массива, a Prev() передвигает ее на один элемент назад.

Функция current() возвращает не ключ, а величину текущего элемента (если он не указывает на конец массива).

Основное достоинство косвенного перебора – «читабельность» и ясность кода, а также то, что массив можно перебрать как в одну, так и в другую сторону.

Недостатки косвенного перебора:

1 Вложенные циклы. Нельзя одновременно перебирать массив в двух вложенных циклах или функциях. Так как второй вложенный for «испортит» положение текущего элемента у первого for'a.

2 Нулевой ключ. Если в массиве встретится ключ 0:

for(Reset($Names);($k=key($Names));Next($Names))

echo "Возраст $k – {$Names[$k]} лет\n";

то в этом случае выражение ($k=key ($Names)), будет равно нулю и цикл оборвется.

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

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

for(Reset($Names);list($k,$v)=each($Names);

/*пусто*/)

echo "Возраст $k – $v\n";

В начале заголовка цикла используется функция Reset(). Дальше переменным $k и $v присваивается результат работы функции each(). Третье условие цикла просто отсутствует.

Функция each() во-первых, возвращает список, нулевой элемент которого хранит величину ключа текущего элемента массива $Names, а первый – значение текущего элемента. Во-вторых, она продвигает указатель текущего элемента к следующей позиции. Если следующего элемента в массиве нет, то функция возвращает не список, a false. Поэтому она и размещена в условии цикла for и не указан третий блок операторов в цикле for: он просто не нужен, ведь указатель на текущий элемент и так смещается функцией each ().

Перебор в стиле РНР. Прямой перебор массивов можно осуществить с помощью функции foreach:

foreach($Names as $k=>$v)

echo "Возраст $k – $v\n";

Этот способ перебора работает с максимально возможной скоростью – даже быстрее, чем перебор списка при помощи for и числового счетчика.