Главное меню

Загрузка массивов из файлов

В разделе "Хранение и выборка данных" вы узнали, как сохранить в файле заказы клиентов. Каждая строка результирующего файла выглядит приблизительно так:

12:33, 26th February 4 покрышек 1 масла 6 свечей $434.00 ул. Гудвина, 12, г. Изумрудный

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

Загрузка массивов из файлов

Этот сценарий генерирует почти такой же вывод, как и показанный на рис. 2.4, который выдан сценарием из листинга 2.3 (см. здесь). Однако на сей раз мы использовали функцию file (), которая загружает весь файл в массив. Каждая строка файла становится отдельным элементом массива. В этом сценарии также применяется функция count () для подсчета количества элементов в массиве.

Более того, каждый раздел строк заказа можно также загрузить в отдельный элемент массива, чтобы разделы можно было обрабатывать по отдельности или посредством выбора соответствующего формата придать им более привлекательный вид. Именно это и делает сценарий, представленный в листинге 3.3.

Загрузка массивов из файлов

Код, показанный в листинге 3.3, загружает весь файл в массив, однако, в отличие от примера, приведенного в листинге 3.2, в нем используется функция explode () для разбиения каждой строки, чтобы перед выводом ее можно было подвергнуть определенной обработке и форматированию.

Генерируемый этим сценарием вывод показан на рис. 3.6.

Загрузка массивов из файлов

Функция explode () имеет следующий прототип:

array explode(string separator, string string [, int limit])

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

explode("\t", $orders[$i])

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

12:33, 26th February\t 4 покрышек\t 1 масла\t 6 свечей\t $434.00\t ул. Гудвина, 12, г. Изумрудный

разбивается на части:

"12:33, 26th February", "4 покрышек", "1 масла", "6 свечей", "$434.00" и "ул. Гудвина, 12, г. Изумрудный".

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

В данном случае объем обработки не особенно велик. Вместо того чтобы в каждой строке выводить название товара (покрышки, бутылки масла и свечи зажигания), в ней отображается только заказанное количество каждого из них, а таблица снабжается строкой заголовка, показывающей, что означает каждое из значений.

Существует ряд способов возможного извлечения чисел из этих строк. В данном случае использовалась функция intval (). Как было отмечено в первом разделе, эта функция преобразует тип string в тип integer. Преобразование в этом примере выполняется достаточно рационально, оно игнорирует такие фрагменты строки, как метка, которые не могут быть преобразованы в integer. Различные способы обработки строк рассмотрим далее.

Другие манипуляции с массивами

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

Перемещение внутри массива: функции each (), current(), reset(), end(), next(), pos() и prev()

Ранее упоминалось, что каждый массив имеет внутренний указатель, который указывает на текущий элемент массива. Выше мы косвенно задействовали этот указатель при использовании функции each (), но им можно пользоваться и манипулировать непосредственно.

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

Вызов функции next () или each () перемещает указатель вперед на один элемент. Вызов функции each ($array_name) возвращает текущий элемент, прежде чем переместить указатель. Функция next () ведет себя несколько иначе – в результате вызова функции next ($array_name) сначала перемещается указатель, а только после этого возвращает новый текущий элемент.

Мы уже видели, что функция reset () возвращает указатель на первый элемент массива. Аналогично, вызов функции end ($array_name) перемещает указатель в конец массива. Функции reset () и end() возвращают, соответственно, первый и последний элементы массива.

Для перемещения в массиве в обратном направлении можно воспользоваться функциями end () и prev (). Функция prev () является обратной по отношению к функции next (). Она перемещает текущий указатель на один элемент назад, а затем возвращает новый текущий элемент.

Например, приведенный ниже фрагмент кода выводит элементы массива в обратном порядке:

$value = end($array);

while ($value) {

echo "$value<br />";

$value = prev($array);

}

Например, если массив $array объявлен следующим образом:

$array = array (1, 2, 3);

то вывод в окне браузера будет выглядеть так:

3

2

1

Используя функции each (), current (), reset (), end (), next (), pos () и prev (), вы можете написать свой собственный код, позволяющий перемещаться в массиве в любом порядке.

Применение любой функции к каждому элементу массива: функция array_walk ()

Иногда требуется выполнять одинаковые действия над каждым элементом массива. Сделать это позволяет функция array_walk ().

Функция array_walk() имеет следующий прототип:

bool array_walk(array arr, string func, [mixed userdata])

Подобно тому, как мы поступали при вызове функции usort (), с которой уже приходилось иметь дело, при вызове функции array_walk() предполагается использование вашей собственной функции.

Функция array_walk() принимает три параметра. Первый параметр arr – это массив, подлежащий обработке. Второй параметр, func, представляет собой имя определяемой пользователем функции, которая будет применяться к каждому элементу массива. Третий параметр, userdata, является необязательным. В тех случаях, когда он используется, он передается определяемой пользователем функции в качестве параметра. Его применение будет продемонстрировано несколько ниже.

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

Следующий фрагмент кода отображает каждый элемент с новой строки, вызывая пользовательскую функцию my_print () для каждого элемента массива $array:

function my_print($value) {

echo "$value<br />";

}

array_walk($array, 'my_print');

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

yourfunction(value, key, userdata)

В большинстве случаев определенная вами функция использует только значения, хранящиеся в массиве. В некоторых случаях функции придется передавать некоторые данные через параметр userdata.

Иногда наряду со значением того или иного элемента массива интерес может вызвать и его ключ. Созданная вами функция может просто игнорировать и ключ, и параметр userdata, как это имеет место в my_print ().

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

function my_multiply(&$value, $key, $factor) {

$value = $factor;

}

array_walk(&$array, 'my_multiply', 3) ;

В этом примере определена функция my_multiply (), которая будет умножать каждый элемент массива на заданный коэффициент. В данном случае нам необходимо использовать необязательный третий параметр функции array_walk() с тем, чтобы передать его в функцию my_multiply () и использовать как коэффициент умножения. Поскольку нам нужен этот параметр, функцию my_multiply () необходимо определить так, чтобы она принимала три параметра – значение элемента массива ($value), ключ элемента массива ($kеу) и коэффициент умножения ($factor). В данном случае ключ нам не нужен.

Обратите внимание на то, как мы передаем в функцию параметр $value. Символ амперсанда (&) перед именем переменной в определении функции my_multiply () означает, что $value будет передаваться по ссылке. Передача по ссылке позволяет функции изменять содержимое массива.

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

Подсчет элементов в массиве: функции count (), sizeof () и array_count_values ()

В приведенном ранее примере для подсчета количества элементов в массиве заказов использовалась функция count (). Функция sizeof () служит тем же целям. Обе функции возвращают количество элементов в переданном им массиве. Так, значение счетчика количества элементов будет равно 1 для обычной скалярной переменной и 0 при передаче либо пустого массива, либо переменной без установленного значения.

Функция array_count_values () сложнее.

Если вызвать array_count_values ($array), то эта функция подсчитает, сколько раз встречается в массиве $array каждое уникальное значение. (То есть эта функция определяет мощность множества для данного массива.) Она возвращает ассоциативный массив, содержащий таблицу частоты использования элементов. Этот массив содержит в качестве ключей все уникальные значения массива $array. Каждый ключ имеет числовое значение, указывающее, сколько раз соответствующий ключ встречается в массиве $аггау.

Например, следующий код:

$array = array(4, 5, 1, 2, 3, 1, 2, 1);

$ас = array_count_values($array);

создает массив $ас, который содержит:

Ключ Значение
4 1
5 1
1 3
2 2
3 1

 

Этот результат показывает, что ключи 4, 5 и 3 встречаются в массиве $array по одному разу, 1 – три раза, а 2 – дважды.

Преобразование массивов в скалярные переменные: функция extract ()

Массив с содержательными индексами, содержащий пары “ключ-значение”, с помощью функции extract () можно преобразовать в набор скалярных переменных. Эта функция имеет следующий прототип:

extract (array var_array [, int extract_type] [, string prefix] );

Функция extract () предназначена для создания скалярных переменных, имеющих те же имена, что и ключи массива. Переменным присваиваются значения, равные значениям, которые хранятся в массиве.

Ниже показан простой пример.

$array = array( 'key1’ => 'value1', 'key2' => 'value2', 'kеуЗ' => 'value3');

extract($array);

echo "$key1 $key2 $key3";

Этот фрагмент кода генерирует следующий вывод:

value1 value2 value3

Массив содержал три элемента с ключами key1, key2 и kеуЗ. Благодаря использованию функции extract () были созданы три скалярные переменные $key1, $kеу2 и $kеуЗ. Как видно из вывода, значениями переменных $key1, $kеу2 и $kеуЗ являются, соответственно, 'value1', 'value2' и 'value3'.

Функция extract () принимает два необязательных параметра: extract_type и prefix. Переменная extract_type задает функции extract () способ обработки конфликтных ситуаций. Такие ситуации возникают, когда переменная с именем, содержащимся в ключе, уже существует. По умолчанию значение существующей переменной заменяется новым. Допустимые значения параметра extract_type перечислены в табл. 3.2.

Загрузка массивов из файлов

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

$array = array( 'key1' => 'value1', 'key2' => 'value2', 'kеуЗ' => 'value3');

extract($array, EXTR_PREFIX_ALL, 'my_prefix');

echo "$my_prefix_key1 $my_prefix_key2 $my_prefix_key3";

Этот код снова сгенерирует вывод:

value1 value2 value3

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