Сложная сортировка массивов на PHP
Недавно попросили написать скрипт для сортировки данных. Задача довольно простая. Есть многомерный массив. Его нужно отсортировать по трём определённым элементам.
Вначале я по привычке погуглил, но нашёл или монстрообразные или нерабочие решения. Поэтому пришлось писать скрипт самому. А решение оказалось очень простым.
Дано
На входе у нас текстовая база данных database.csv, записи которой разбросаны как попало. Нам нужно отсортировать записи по 3 параметрам, а затем записать в новый файл new_database.csv.
Для примера возьмём простенькую БД (см. ниже). Нам нужно отсортировать данные по стране, затем по городу, и затем по улице. Другие поля для наглядности опустим, но их может быть сколько угодно.
|||Россия|Москва|Петровка|
|||Украина|Чернигов|Валенка|
|||Aвстрия|Вайберг|Симонова|
|||Россия|Адлер|Кучмы|
|||Россия|Москва|Яйцево|
|||Украина|Киев|Ющенко|
|||Украина|Прилуки|Дятлова|
|||Россия|Москва|Путина|
|||Россия|Москва|Склокино|
|||Aвстрия|Фельдбах|Фейрштрассе|
|||Россия|Москва|Жадино|
|||Россия|Москва|Ахтунгово|
|||Украина|Чернигов|Морозова|
Решение
Решение задачи очень простое. Используем функции usort и strnatcmp. Не знаю даже, что здесь можно рассказывать, поэтому просто привожу код.
Весь смысл функции сортировки в том, что мы вначале сравниваем по одному параметру. Если они равны, то по другому. А если и они равны, то по третьему. Прелесть данного решения в том, что оно очень простое, легко внедряется куда угодно и может работать с любым количеством параметров.
// подгружаем файл
$data = file('database.csv');
// заполняем массив данными
foreach ($data as $string)
{
// разбиваем строку
$database[] = explode('|', $string);
}
// функция сортировки
function cmp($a, $b)
{
// в первую очередь сравниваем по стране
if ($a[3] != $b[3])
return strnatcmp($a[3], $b[3]);
// затем сравниваем по городу
elseif ($a[4] != $b[4])
return strnatcmp($a[4], $b[4]);
// и наконец сравниваем по улице
else
return strnatcmp($a[5], $b[5]);
}
// сортировка базы данных
usort($database, 'cmp');
// собираем данные в строку
foreach ($database as $key => $string)
$new_data .= implode('|', $string);
// запись в файл
file_put_contents('new_database.csv', $new_data);
Если нужно сравнивать строки независимо от регистра, то нужно использовать функцию strnatcasecmp.
За решение этой задачи у моего знакомого фрилансеры попросили 4000 рублей. Как думаете, стоит оно того?
И конечно комментарии приветствуются.
В рамках обмена
Многие вебмастера любят обвесить свои сайты разнообразными флешечками и рюшечками (их ещё называют свистелками и перделками). И конечно же заказчики обожают такие спецэффекты. Поэтому в вебмастеркой блогосфере очень популярны подборки jQuery скриптов. Читайте пост по ссылке и узнаете о существовании целых 10 украшений для вашего сайта.
Поделиться ссылкой:
Комментарии:
Раз есть спрос за такую цену - значит, столько и стоит. :) Ну а в производительности, думаю, шустро работает. Возьму на заметку.
Я думаю стоит, человек который может это быстро сделать должен еще знать свою цену
Чувак. Фрилансеры не от хорошей жизни фрилансеры. А ты даешь им задачу, а потом делаешь загогулину - мол, «а я и сам могу, пардонь-те!» Эх эх эх.
Пойду регистрироваться на фриланс сайтах, за такие деньги такие несложные задачи решать... :) Кстати, в цену можно добавить популярность кодера или репутацию, может поэтому такая цена. Хорошая репутация залог качественной работы.
Думаю стоит - все зависит от реализации, тем более что в нашем примере для наглядности остальные параметры убраны. Цена она от много зависит)
Другое дело, сколько он по времени сказал это будет делать)
Never Lex ну ты крут батька. Для понта решаешь детские задачки и постишь об этом в блог. Асталависта :)
отличное решение на основе встроенной функции, в духе php. что мешает хранить данные в *sql базе?
Задача, полюбому, коммерческой тематики. И если обратились к фрилансерам, значит штатного программиста либо нет, либо он не справился с поставленной задачей. Поэтому ценник вполне адекватен.
Выше, приведено решение которое решает только конкретную задачу, не буду судить плохо оно или хорошо. Но часто бывает необходимо оперировать массивами в виде рекордсета, где каждый элемент массива «строка» сам является массивом - «колонки» с данными. Естественно нужно иногда сортировать по нескольким полям сразу.
Для этого можно воспользоваться array_multisort.
В комментариях на http://php.net/manual/en/function.array-multisort.php есть примеры использования этой функции для сортировки рекордсетов. Между версиями 5.2 и 5.3 есть разница, так что обратить на это внимание.
«За решение этой задачи у моего знакомого фрилансеры попросили 4000 рублей. Как думаете, стоит оно того?»
Алексей, теперь я буду делать это за 200 рублей :D
4000 это слишком много. На эту сумму можно отличный дизайн заказать у тебя :)
ничего сложного, только этот алгоритм не оптимальный по количеству операций
сортировка с разделением хотя бы
Если заплатили, значит стоит. Конечно работа не такая уж и пыльная, но если за это платят, значит стоит. К сожалению в нашем мире всегда так, за сложную работу -платят мало, а за протирание штанов - в основном больше. А алгоритмы и оптимизация доступны не каждому даже умному человеку, поэтому оно того стоит.
давно программирую на php. могу сказать что с массивами работать на нем гораздо удобнее нежели на других языках.например на перл мне кажеться черт ногу сломит ))
Спасибо, я это очень долго искал, и вдруг наткнулся у вас в блоге... Спасибо вам огромное еще раз! =)
А зачем собственно эта сортировка используется? Я просто не понимаю малость видать. Если код настолько прост для написания, то наверняка 4к за него это многовато, хотя всякое бывает!
«За решение этой задачи у моего знакомого фрилансеры попросили 4000 рублей. Как думаете, стоит оно того?»
Цена уменьшается прямо пропорционально росту количества людей, знающих решение :)
Так получилосб что у меня в одной БД несколько сайтов, как проще их разделить?
Не хватает у меня сил на нормальное изучение php, предпочитаю все аутсорсить фрилансерам. Считаю что каждый должен делать только то, что умеет.
Пробовал я себя в PHP. Ну не моё это. А почитаешь вас вроде и не сложно.
Думаю примерчик пригодиться.
За скриптик спасибо, каждый должен заниматься тем, чем любит и умеет - это понятно, но даже человек, не имеющий отношения к программированию, может что-то с чем-то связать, ведь вас не программировать сложные структуры заставляют, а просто пораскинуть мозгами и поиском в гугле. %))
кстати говоря. скрипт полезен, но только в конкретном случае. то есть если бы заказчику понадобилось бы во первых использовать другой структуры csv файл и во вторых нужно было бы производить другую сортировку(я не говорю о дополнительных действиях), то мягко говоря решение могло быть сложнее. Я хочу сказать что в принципе в определенных задачах иногда находятся простые решения, а не огромные какие нибудь скрипты, имеющих более обобщенные ситуации, и чаще всего выполняющие лишние действия. Но я люблю когда находятся именно простые решения. Ведь в этом и заключается мастерство программирования
Не могу решиться учить php или нет, т.к. знакомый программист говорит, что при верстке сайта оно мне не поможет, что лучше javascript. Кто, что может посоветовать, стоит ли париться с php?
Прикольно у вас тут. Без меня не скучаете? :-)
По поводу задачи.
1) то, что вы называете csv на самом деле csv не является. Учим матчасть: http://ru.wikipedia.org/wiki/CSV
2) если данные расположены в исходном файле именно так, как Вы указали, то решение будет таким:
$data = file(’database.csv’);
sort($data);
file_put_contents(’new_database.csv’, $data);
и не нужно городить велосипед ;-)
Never Lex,
Ууух, побежал регаться на фриланс-форумах) Задачка - олимпиада по программированию класса эдак 5-го (имеется ввиду Белорусская олимпиада, т.к. с Российскими не знаком). За это давать 4000? Просто смешно честно говоря)
П.с. Неверлекс, чего-то от тебя рассылки давно не видно, это ты не отсылал уже давно, или она до меня по каким-либо причинам просто не доходит?
Мой знакомый подобный скрипт писал за 20$. Мне кажется это борщ 4000 рублей
Не, ну это дорого. А вообще интересно знать, сколько будут брать за 8 часов работы при 24 дневной занятости?
В какомто учебнике по php тоже встречал такое решение с использованием ф-й usort и strnatcmp
цена завышена оттого что все заказчики выбирают ПРО-шников, забывая о начинающих программистах, которые как раз таки и решили бы эту задачу за 200р. ну или за 300р. :)
На счет уппрощения...
Если перестать ёрничать на счет исходных форматов и прочей фигни, то более шустрым решением будет примерно такое (комментарии выкинул - и так все понятно):
<?php
$data = file(’database.csv’);
for($i=0, $c=count($data); $i<$c; $i++)
{
$a = explode(’|’, $data[$i]);
$database[] = array($a[3].’ ’.$a[4].’ ’.$a[5], $data[$i]);
}
usort($database, ’cmp’);
$new_data = ’’;
for($i=0; $i<$c; $i++)
$new_data .= $data[$i][1];
// запись в файл
file_put_contents(’new_database.csv’, $new_data);
function cmp($a, $b) { return strnatcmp($a[0], $b[0]); }
?>
Быстрее, потому, что содержит в разы меньше вызовов функций и ветвлений, т.е. самых «прожорливых» в плане скорости операций . Хотите убедиться - создайте файл с миллионом строк и прогоните его через оба скрипта.
Не работает.
Естественно не работает, т.к. писался прямо в комментарии форума и ни разу не запускался вживую. Имя переменной перепутано. Вместо $new_data .= $data[$i][1]; должно быть $new_data .= $database[$i][1];
Неужели трудно было заметить эту опечатку?
ЗЫ
Работает прекрасно даже с данными в UTF-8.
ЗЗЫ
Добавьте в редактор комментариев ББ-тэг для вставки кода, будет удобнее.
Обычно когда я пишу какой-то скрипт или программу, я не лезу в Google за исходниками, а пытаюсь сам написать программу(скрипт). Потом уже лезу в Google и сравниваю свой исходник с уже готовыми.
Sibluder, на мой взгляд так и следует делать, так сказать учиться самим у себя.
Согласна, если есть спрос, то и цена такой работе должна быть соотвотственная. Кому-то, чтоб заработать эти деньги пришлось бы попотеть.
Я раньше в делфы это делал, так что мне это и в ПХП сделать будет не трудно.
Я недавно начал изучать PHP потому что идей много и денег не так много )) Своими силами сложнее, но потом экономия. Спасибо за статью.. пришлось правда въезжать немного...
тут не учитывается регистр букв, нужно приводить символы либо в верхний либо в нижний регистр
НЕКРОПОСТ!!
Берут 4к, чтобы такую херню не писали =)
А что если csv у тебя на 500мб?
Твой скрипт упадет в allowed size memory
Памяти хватит,целиком файл читать?)
отличное решение на основе встроенной функции, в духе php. что мешает хранить данные в *sql базе?
Array Sorting is a skill Everyone should learn. Great job on this. Thank you for sharing this detailed article.
Array Sorting is a skill Everyone should learn. Great job on this. Thank you for sharing this detailed article.
Думаю врятли это столько стоит, максимум 2к, хотя все зависит от значимости данного решения.