|
|
|
| Имеется три массива $m_1, $m_2 и $m_3.
Первый массив содержит буквенно-цифровые элементы, разделенные пробелами:
$m_1[1] = “n 1 1 7”;
$m_1[2] = “9 95”;
$m_1[3] = “n 117”;
$m_1[4] = “99 5”;
$m_1[5] = “1 23”;
|
Элементы второго массива образованы из элементов первого массива путем удаления пробелов:
$m_2[1] = “n117”;
$m_2[2] = “995”;
$m_2[3] = “n117”;
$m_2[4] = “995”;
$m_2[5] = “123”;
|
Элементы третьего массива являются строками, некоторые из которых повторяются:
$m_3[1] = “молоко”;
$m_3[2] = “молоко”;
$m_3[3] = “молоко”;
$m_3[4] = “молоко свежее”;
$m_3[5] = “молоко”;
|
Требуется из всех массивов удалить элементы, для которых пара второй-третий массив неуникальны. Для данного примера нужно удалить элементы $m_1[1], $m_2[1] и $m_3[1] либо $m_1[3] , $m_2[3] и $m_2[3], поскольку для них одинаковы пары «n117 – молоко».
Как это сделать на РНР, без использования MySQL? | |
|
|
|
|
|
|
|
для: Владимир55
(10.09.2012 в 21:58)
| | Не пишите кавычек таких, это ошибка в РНР и, если копировать ваши данные, то значит производить замену их.
Можно пройти циклом со сравнением, забирая только уникальные значения (как строка значений второго плюс третьего массива). Можно выполнить с помощью функций стандартных, получив уникальные ключи, а по ним необходимое. Способов много. Вот с помощью стандартных функций:
<?
$m_1 = array("n 1 1 7", "9 95", "n 117", "99 5", "1 23");
$m_2 = array("n117", "995", "n117", "995", "123");
$m_3 = array("молоко", "молоко", "молоко", "молоко свежее", "молоко");
echo '<pre>';
//формируем массив уникальных значений
$a = array_unique(array_map(function($a, $b) {
return $a.' '.$b;
}, $m_2, $m_3));
print_r($a);
//по ключам этого массива получаем необходимые массивы из трех источников
$m_1 = array_intersect_key($m_1, $a);
print_r($m_1);
$m_2 = array_intersect_key($m_2, $a);
print_r($m_2);
$m_3 = array_intersect_key($m_3, $a);
print_r($m_3);
| Но это ради того, чтобы знать, что можно "творить" с помощью стандартного набора, а вот на практике, все таки лучше в MySQL (надо полагать данные из нее), так как в запросе можно соединить в строку эти значения, и выбрать только уникальные записи. | |
|
|
|
|
|
|
|
для: confirm
(11.09.2012 в 01:44)
| | Не пишите кавычек таких, это ошибка в РНР
Тему в ворде писал - оттуда и такие кавычки переползли.
на практике, все таки лучше в MySQL
В MySQL это было бы удобно, но в скрипте база не используется, а подключать её только ради этого не хотелось.
К тому же, Вы создали такое элегантное решение, что так даже лучше.
Однако данный конкретный код не работает. Выводится сообщение:
Parse error: syntax error, unexpected T_FUNCTION, expecting ')' in test.php on line 7
|
| |
|
|
|
|
|
|
|
для: Владимир55
(11.09.2012 в 10:02)
| | Все скобки на месте, у меня ведь работает, коли я "был недоволен" ) вашими скобками, значит я копировал, а если копировал, значит запускал.
Что за версия РНР у вас?
Начиная с версии 5.3.0 всегда доступно расширение SPL, которое богато итераторами, которые для решения подобных задач (начиная с начала) куда более элегантнее. | |
|
|
|
|
|
|
|
для: confirm
(11.09.2012 в 10:13)
| | PHP Version 5.2.12.
Версии выше я применять не могу, поскольку нужен Zend Optimizer , а он в 5.3 не поддерживается.
Нет ли способа реализовать в 5.2 ? | |
|
|
|
|
|
|
|
для: Владимир55
(11.09.2012 в 11:37)
| | Да он везде будет работать, так как нет никакой ошибки. Выполните тоже самое, но по-проще, с меньшим числом аргументов:
<?
$m = array("n 1 1 7", "9 95", "n 117", "99 5", "1 23");
echo '<pre>';
$a = array_map( //открываем скобку аргументов функции обхода массива
function( //объявляем функцию являющуюся первым аргументом функции обхода массива
//и открываем скобку перед ее аргументами
$аргумент_объявленной_функции
) //закрываем скобку после аргументов объявленной функции
{ //открываем фигурную скобку тела объявленной функции
return str_replace( //выполняем вложенную функцию, и открываем скобку ее аргументов
' ','',$аргумент_объявленной_функции
); //закрываем скобку аргументов вложенной функции, и закрываем строку кода
}, //закрываем фигурную скобку тела объявленной функции
$m //второй аргумент функции обхода массива
); //закрываем скобку аргументов функции обходя массива, и закрываем строку кода
print_r($a);
| В примере расписана каждая скобка. Так же можно описать и скобки примера приведенного ранее. | |
|
|
|
|
|
|
|
для: confirm
(11.09.2012 в 12:01)
| | Я тоже знаю, что все скобки на месте. Поэтому и привел диагностическое сообщение полностью, а не пересказал его.
Однако и этот, сокращенный код, не работает. Причем, ни на сервере, ни на Денвере. Диагностика та же, только относится к line 6.
Вот такая загадка... | |
|
|
|
|
|
|
|
для: Владимир55
(11.09.2012 в 13:10)
| | Да нет ничего загадочного, надо полагать, что это связано с объявлением анонимных функций, которая и применяется в примере. Анонимные функции появились в РНР 5.3.0 (у меня версия 5.3.9). Значит в вашей версии этот пример работать не будет. Другого объяснения я не нахожу.
Для вашей версии, возможен только один выход (именно для использования этого примера), это создание анонимной функции посредством create_function, или проход массива в цикле запоминать/сравнивать. | |
|
|
|
|
|
|
|
для: confirm
(11.09.2012 в 14:06)
| | create_function, по идее, должна работать и с версией 5.2. Но я этого никогда не делал.
Можете Вы написать её для созданного Вами решения? | |
|
|
|
|
|
|
|
для: Владимир55
(11.09.2012 в 14:13)
| | Не по идее, а будет работать, это "дедушка" объявления лямбда-функции. Замените код создание массива уникальных значений на этот:
<?
//формируем массив уникальных значений
$a = array_unique(array_map(create_function('$a, $b', 'return $a." ".$b;'), $m_2, $m_3));
|
PS. Лучше обновлять РНР, устанавливая последнюю рабочую версию, даже, если, придется слегка править код для этого (правда, если следовать рекомендациям разработчиков, то вряд ли такое придется делать).
Можно эту задачу решить с помощью итераторов. Для работы с итераторами нужно расширение SPL, которое доступно и включено по умолчанию начиная с версии PHP 5.0.0, то есть в вашей есть. Но давать пример на них я не буду, вам трудны для понимания и простые примеры (насколько можно судить), а итераторы, это "тяжелая артиллерия" для понимания, если конечно не изучать РНР (его возможности).
Или циклы, что с точки зрения производительности (в случае большого объема этих массивов) выгоднее чем цепочка функций. Но, если рассматривать задачу изначально, начиная с первоначальных данных (то есть, ваши действия: данные-->получили массив-->еще связанные данные-->результат), то вполне может быть и оправдано применение array_map/array_walk+create_function, которое бы вернуло уже готовый результат - три массива только уникальных значений. | |
|
|
|
|
|
|
|
для: confirm
(11.09.2012 в 14:23)
| | Отлично все заработало, спасибо!
Интересное, яркое решение! | |
|
|
|
|
|
|
|
для: Владимир55
(10.09.2012 в 21:58)
| | Изначальные и ключевые массивы, я так понимаю, 1 и 3, а массив номер 2 вспомогательный и в конечном итоге нужно получить 1 и 3 массив без повторений связанных строк.
Для полного понимания ситуации расскажите как формируются массивы 1 и 3, на мой взгляд несколько странное хранение данных или это тоже промежуточный результат? | |
|
|
|
|
|
|
|
для: Valick
(11.09.2012 в 15:11)
| | Изначальные и ключевые массивы, я так понимаю, 1 и 3, а массив номер 2 вспомогательный и в конечном итоге нужно получить 1 и 3 массив без повторений связанных строк.
Так и есть.
как формируются массивы 1 и 3, на мой взгляд несколько странное хранение данных или это тоже промежуточный результат?
Это окончательный результат.
Данные приходят из удаленной базы и они явялются таким по той причине, что владельцы базы их собирали из каталогов производителей разных стран. Кто что наисал, то и хранится в их базе.
Выборка для пользователя получается небольшая - сто-двести строк на экране, но обилие повторов не нравится даже мне самому. | |
|
|
|
|