Найти тему
ZDG

Введение в язык PHP #3: Коллекции

Предыдущие части: Переменные, строки и среда исполнения, Введение в PHP

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

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

А понадобятся нам, конечно же, коллекции. Что это такое, и для чего используется, я подробно описывал в отдельном цикле.

Какие типы коллекций есть в PHP?

Отвечать на этот вопрос легко и приятно: в PHP есть ровно один тип коллекций, и это ассоциативный массив.

Давайте вспомним, что такое массив. Это область памяти, последовательно заполненная элементами. У нас есть начало массива в виде адреса памяти. Назовём этот адрес "a". Чтобы получить первый элемент массива, нужно прибавить к адресу смещение 0:

a[0]

Чтобы получить второй элемент, нужно прибавить к адресу смещение 1:

a[1]

И так далее.

Посмотрим, как инициализировать массивы в PHP:

$a = [];

Мы создали пустой массив с именем $a.

$a = [1, 2 , 3];

Мы создали массив с именем $a, который состоит из трёх элементов: 1, 2, 3. Эти элементы находятся по соответствующим смещениям от начала массива:

$a[0] = 1
$a[1] = 2
$a[2] = 3

Но трюк здесь в том, что массив – ассоциативный. Это значит, что в нём нет линейных смещений, а есть лишь пары "ключ–значение".

То, что выглядит как смещение, на самом деле является ключом. В данном случае значение "1" хранится с ключом "0", значение "2" с ключом "1" и значение "3" с ключом "2".

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

$a['0'] = 1
$a['1'] = 2
$a['2'] = 3

PHP не делает разницы между ключом, например, 0 (т.е. целочисленным) и '0' (т.е. строковым). На этом погорели многие программисты.

Также можно использовать любые другие ключи:

$a['one'] = 1
$a['two'] = 2
$a['three'] = 3

Чтобы инициализировать массив с произвольными ключами, нужно написать так:

$a = ['one' => 1, 'two' => 2, 'three' => 3];

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

$a = [0 => 1, 2 => 2, 3 => 3];

Здесь мы начали с ключа 0, затем пропустили ключ 1 и поставили следующим ключ 2. То есть данный массив будет выглядеть так:

$a[0] = 1
$a[2] = 2
$a[3] = 3

В нём не будет элемента с ключом 1.

В общем, нужно помнить две вещи:

  • Ключи типа 0 и '0' не различаются
  • Это всегда ассоциативные массивы с набором пар "ключ–значение", всё остальное (смещения, номера) лишь иллюзия.

Работа с ассоциативными массивами

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

$a = [1, 2, 3, 4, 5];

В этом случае каждый элемент массива автоматически получает последовательное смещение-ключ, начиная с 0. И вы можете работать с таким массивом, например, в цикле:

for ($i = 0; $i < 5; $i++) $a[$i] *= 2;

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

$a = [];
for ($i = 0; $i < 5; $i++) $a[] = $i;

Конструкция $a[] добавляет в конец массива новый элемент и назначает ему ключ, следующий по порядку.

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

$a = [];
for ($i = 0; $i < 5; $i++) $a[$i] = $i;

Здесь вместо $a[] мы пишем $a[$i]. Это тоже будет создавать новые элементы в массиве с ключом $i. Так как $i меняется в цикле последовательно от 0 до 4, то результат будет тот же, что и выше.

В общем, новый элемент в массиве создаётся в двух случаях:

$a[] = 10;

– создать новый элемент в конце массива, дать ему ключ-смещение автоматически;

$a[$b] = 10;

– создать новый элемент массива с ключом $b. Если такой ключ уже существует в массиве, то новый элемент не создаётся, а его значение просто перезаписывается.

Итераторы

Если массив, в котором ключи являются последовательными числами 0, 1, 2 и т.д., мы можем обойти с помощью цикла, то как быть с массивом, где ключи заданы произвольно? Например:

$a = ['one' => 1, 'two' => 2, 'three' => 3];

Для этого есть конструкция foreach:

foreach($a as $value) echo "$value\n";

Буквально её можно перевести так: "для каждого элемента из $a, который мы назовём $value..."

Переменная $value внутри цикла foreach будет последовательно принимать значения из массива $a, пока они не закончатся.

Второй вариант foreach это:

foreach($a as $key => $value) echo "$key = $value\n";

Это буквально переводится так: "для каждой пары ключ–значение из $a, которую мы назовём $key => $value..."

Отличие здесь в том, что кроме значения элемента массива ($value) мы также получаем его ключ ($key).

Наконец, есть ещё один вариант обхода. Можно получить массив ключей массива:

$a = ['one' => 1, 'two' => 2, 'three' => 3];
$a_keys = array_keys($a);

В результате массив $a_keys будет содержать элементы: 'one', 'two', three'. Этот массив мы можем обойти уже обычным циклом, достать из него ключи, и использовать эти ключи, чтобы уже достать значения из массива $a:

for ($i = 0; $i < 3; $i++) echo $a[$a_keys[$i]] . "\n";

Также можно получить значения массива:

$a_values = array_values($a);

Мы получим массив $a_values, в котором содержатся те же самые значения, что и в массиве $a, но ключи у этих значений будут пересозданы заново в виде смещений 0, 1, 2..., то есть их можно будет обойти простым циклом.

Поиск в массиве

Чтобы найти элемент в массиве, мы можем воспользоваться функцией in_array():

if (in_array('aaa', $a)) echo "OK\n";

В данном примере, если массив $a содержит элемент со значением 'aaa', то результат будет "истина".

Можно также искать не значение элемента, а его ключ:

if (array_key_exists('one', $a)) echo $a['one'];

В данном примере мы ищем ключ 'one', и если он существует, то печатаем значение элемента с этим ключом.

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

Добавление элементов мы уже рассмотрели (и дополнительно рассмотрим ниже), а вот чтобы удалить элемент, нужно написать так:

unset($a['one']);

В данном примере мы удалили из массива $a элемент с ключом 'one'. При этом неважно, был там такой элемент или нет. Если он был, то он удалится. Если его не было, значит, ничего и не произойдёт.

Мы также можем удалять последний элемент массива с помощью array_pop():

array_pop($a);

В данном примере мы удалили из массива $a последний элемент. Этот последний элемент можно выкинуть, а можно присвоить чему-нибудь, если он нам ещё нужен:

$last = array_pop($a);

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

array_push($a, 10);

В данном примере мы добавили в конец массива $a элемент со значением 10. Эта конструкция идентична рассмотренной выше:

$a[] = 10;

Разница в том, что в array_push() мы можем добавить сразу несколько значений:

array_push($a, 'one', 'two', 'three');

Как нетрудно заметить, функции array_push() и array_pop() имитируют работу стека.

Длина массива

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

$a = [1, 2, 3];
$c = count($a);

Переменная $c будет равна 3.

Заключение

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

Дополнительно в документации PHP описаны функции работы с массивами, которые позволяют строить объединение и пересечение массивов и многое другое.