[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Задачка на сортировку многомерного массива
DorianLeroy
Всем привет, вот на собеседовании дали интересную задачу - не думал что окажет сопротивление, однако - бился довольно долго, так и не надумал изящное решение.


Дан многомерный массив вида

Array (
[
0] => Array ( [id] => 1 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_0_2 )
[
1] => Array ( [id] => 2 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_0_1 )
[
2] => Array ( [id] => 3 [c_name_eng] => Ukraina eng ID1 [c_name_rus] => Город 1_0_1 )
[
3] => Array ( [id] => 5 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_0_2 )
[
4] => Array ( [id] => 13 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_0_1 )
[
5] => Array ( [id] => 20 [c_name_eng] => Ukraina eng ID1 [c_name_rus] => Город 1_0_2 )
[
0] => Array ( [id] => 7 [c_name_eng] => Ukraina eng ID1 [c_name_rus] => Город 1_3_2 [r_name_rus] => Крым ID3 )
[
1] => Array ( [id] => 8 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_4_3 [r_name_rus] => Дальний восток ID4 )
[
2] => Array ( [id] => 10 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_1_2 [r_name_rus] => Центральные области ID1 )
[
3] => Array ( [id] => 11 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_2_2 [r_name_rus] => Центральная Россия ID2 )
[
4] => Array ( [id] => 12 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_4_1 [r_name_rus] => Дальний восток ID4 )
[
5] => Array ( [id] => 14 [c_name_eng] => Ukraina eng ID1 [c_name_rus] => Город 1_3_1 [r_name_rus] => Крым ID3 )
[
6] => Array ( [id] => 15 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_1_1 [r_name_rus] => Центральные области ID1 )
[
7] => Array ( [id] => 16 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_4_2 [r_name_rus] => Дальний восток ID4 )
[
8] => Array ( [id] => 17 [c_name_eng] => Russia eng ID2 [c_name_rus] => Город 2_2_1 [r_name_rus] => Центральная Россия ID2 )
[
9] => Array ( [id] => 18 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_1_5 [r_name_rus] => Центральные области ID1 )
[
10] => Array ( [id] => 22 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_1_4 [r_name_rus] => Центральные области ID1 )
[
11] => Array ( [id] => 23 [c_name_eng] => Belorus eng ID3 [c_name_rus] => Город 3_1_3 [r_name_rus] => Центральные области ID1 ) )


Внутренние массивы содержат следующие поля
Страна - c_name_eng
Город - c_name_rus
Регион - r_name_rus

Какието города могут содержать регионы какието нет, страны есть у всех городов.

Нужно вывести Данный массив следующим образом:


Страна 1
Город 1
Город 2
Город 3
.....

Регион 1
Город 4
Город 5
Город 6
..........
Регион 2
Город 7
Город 8
Город 9
..........
........

Страна 2
Город 10
Город 11
Город 12
.....

Регион 3
Город 13
Город 14
Город 15
..........
Регион 4
Город 16
Город 17
Город 18
..........
........
........



Уж как только я не сортировал массивы...но сбивает именно то что есть города с регионами а есть - без них.



Спустя 8 минут, 52 секунды (15.09.2011 - 20:08) Winston написал(а):
Я так понял, что встроенные ф-и нельзя, да ?
А есть валидный массив (а не эта распечатка), чтобы вставить в код и работать ?

Спустя 8 минут, 26 секунд (15.09.2011 - 20:17) vital написал(а):
Если забить на всякие там rsort\asort и т.п. Руками не вижу проблемы.
Сначала выбрать страны. Потом регионы к каждой стране. ПОтом города к региону. Потом оставшиеся города к странам без регионов.

Просто дохрена проходов цикла. Но сложности не вижу.

Спустя 30 минут, 52 секунды (15.09.2011 - 20:47) DorianLeroy написал(а):
Winston
К сожалению нет, этот массив получается из сложного SQL запроса к бд...

vital
Я тоже не видел...но чтото не заладилось както))

Спустя 13 минут, 11 секунд (15.09.2011 - 21:01) killer8080 написал(а):
Так, не?
$ar = array (  
array ( 'id' => 1, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_0_2' ),
array ( 'id' => 2, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_0_1' ),
array ( 'id' => 3, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_0_1' ),
array ( 'id' => 5, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_0_2' ),
array ( 'id' => 13, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_0_1' ),
array ( 'id' => 20, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_0_2' ),
array ( 'id' => 7, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_3_2', 'r_name_rus' => 'Крым ID3' ),
array ( 'id' => 8, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_4_3', 'r_name_rus' => 'Дальний восток ID4' ),
array ( 'id' => 10, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_2', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 11, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_2_2', 'r_name_rus' => 'Центральная Россия ID2' ),
array ( 'id' => 12, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_4_1', 'r_name_rus' => 'Дальний восток ID4' ),
array ( 'id' => 14, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_3_1', 'r_name_rus' => 'Крым ID3' ),
array ( 'id' => 15, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_1', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 16, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_4_2', 'r_name_rus' => 'Дальний восток ID4' ),
array ( 'id' => 17, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_2_1', 'r_name_rus' => 'Центральная Россия ID2' ),
array ( 'id' => 18, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_5', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 22, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_4', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 23, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_3', 'r_name_rus' => 'Центральные области ID1' ) );

$out = array();

foreach($ar as $item){
$out[$item['c_name_eng']][(isset($item['r_name_rus']) ? $item['r_name_rus'] : 0)][] = $item['c_name_rus'];
}

echo '<pre>'.print_r($out, 1).'</pre>';

Спустя 10 минут, 5 секунд (15.09.2011 - 21:11) inpost написал(а):
foreach ($arr as $v)
{
preg_match('#^([а-яё])*\s#isuU',$v['c_name_eng'],$country);
$temp = (!isset($v['r_name_rus']) ? 0 : 1);
$newarr[$country[1]][$temp] = array($v['id'],$v['c_name_eng']);
}


Если с 4-м параметром в preg_match не ошибся.
Получится у тебя массив, где первым будет страны, далее идентификатор о наличии или нет области, далее данные, данные не дописал, но легко дописать.

Спустя 8 минут (15.09.2011 - 21:19) alex12060 написал(а):
inpost

Если тебе $val не нужен, я б unset'ил его smile.gif

Спустя 4 минуты, 5 секунд (15.09.2011 - 21:23) inpost написал(а):
alex12060
Ну так я же не дописал, я лишь идею показал smile.gif Там $newarr не полностью заполнен, его уже можно и дописать вручную.
Тогда уже и $country[0] тоже unset, после скрипта $arr unset, $temp тоже самое smile.gif

Спустя 13 минут, 19 секунд (15.09.2011 - 21:36) killer8080 написал(а):
inpost
не фига не понял
...
preg_match('#^([а-яё])*\s#isuU',$v['c_name_eng'],$val,$country);
...

что за $country, четвёртый параметр preg_match - это же флаг user posted image
Цитата
mixed preg_match ( string $pattern , string $subject [, array $&matches [, int $flags [, int $offset ]]] )


PS и в c_name_eng нет кирилицы.

Спустя 7 минут, 9 секунд (15.09.2011 - 21:43) inpost написал(а):
killer8080
$matches в третьем аргументе, а не в четвертом, ошибся, что и думал говоря: "Если с 4-м параметром в preg_match не ошибся.".
Ну а вместо русских, подставить англ.

П.С. исправил matches в своём примере. Русские так и оставил, чтобы запутаннее было smile.gif

Спустя 48 минут, 11 секунд (15.09.2011 - 22:31) killer8080 написал(а):
вот вариант с сортировкой
Свернутый текст
$ar = array (  
array ( 'id' => 1, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_0_2' ),
array ( 'id' => 2, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_0_1' ),
array ( 'id' => 3, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_0_1' ),
array ( 'id' => 5, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_0_2' ),
array ( 'id' => 13, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_0_1' ),
array ( 'id' => 20, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_0_2' ),
array ( 'id' => 7, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_3_2', 'r_name_rus' => 'Крым ID3' ),
array ( 'id' => 8, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_4_3', 'r_name_rus' => 'Дальний восток ID4' ),
array ( 'id' => 10, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_2', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 11, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_2_2', 'r_name_rus' => 'Центральная Россия ID2' ),
array ( 'id' => 12, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_4_1', 'r_name_rus' => 'Дальний восток ID4' ),
array ( 'id' => 14, 'c_name_eng' => 'Ukraina eng ID1', 'c_name_rus' => 'Город 1_3_1', 'r_name_rus' => 'Крым ID3' ),
array ( 'id' => 15, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_1', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 16, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_4_2', 'r_name_rus' => 'Дальний восток ID4' ),
array ( 'id' => 17, 'c_name_eng' => 'Russia eng ID2', 'c_name_rus' => 'Город 2_2_1', 'r_name_rus' => 'Центральная Россия ID2' ),
array ( 'id' => 18, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_5', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 22, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_4', 'r_name_rus' => 'Центральные области ID1' ),
array ( 'id' => 23, 'c_name_eng' => 'Belorus eng ID3', 'c_name_rus' => 'Город 3_1_3', 'r_name_rus' => 'Центральные области ID1' ) );

$out = array();

foreach($ar as $item){
$out[$item['c_name_eng']][(isset($item['r_name_rus']) ? $item['r_name_rus'] : '-')][] = $item['c_name_rus'];
}

ksort($out);
foreach($out as $country => $r){
ksort($out[$country]);
foreach($r as $region => $v){
asort($out[$country][$region]);
}
}



echo '<pre>'.print_r($out, 1).'</pre>';

Спустя 2 минуты, 58 секунд (15.09.2011 - 22:34) DorianLeroy написал(а):
killer8080 шикарно, вот это я называю изящно )
inpost немного не понял Ваш пример.

Сначала отрезаем все лишнее у страны - понятны.
Потом смотрим есть ли регион.
Заполняем новый массив -
 $newarr[$country[1]][$temp] =  array($v['id'],$v['c_name_eng']);

1. Почему у country индекс 1 ?
2. Получается в массив $newarr забиваются значения айди текущего города и его страна...эммм...и что дальше? Как сюда забить название региона и потом вывести это? ... вообщем если что, это так - мысли вслух - я понимаю, что Вы показали общую концепцию как решить задачу, но я как истинный дуб не понял сей концепции =)

Спустя 7 минут, 38 секунд (15.09.2011 - 22:42) killer8080 написал(а):
Цитата (DorianLeroy @ 15.09.2011 - 22:34)
killer8080 шикарно, вот это я называю изящно )

Спасибо конечно, но в пол часа с сортировкой не уложился, вроде, значит собеседование провалил бы unsure.gif

Спустя 6 минут, 6 секунд (15.09.2011 - 22:48) DorianLeroy написал(а):
killer8080 Эмм на самом деле - там задача на час - первая часть выбрать из Mysql довольно не просто запрос...может Вы бы его сделали за 5 мин)

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

Спустя 4 минуты, 42 секунды (15.09.2011 - 22:53) inpost написал(а):
DorianLeroy
$country[1] - попадает то, что в кармане, а значит для Украины будет так:
$array['Ukraine'], так как preg_match берёт первое слово по регулярке.
Далее проверка на существование, для того, чтобы разбить страны на те, что есть регион, и в которых нет региона:
$array['Ukraine'][0] // нет региона
$array['Ukraine'][1] // есть регион
То есть 2 верхних записи, это отдельные массивы, в которых уже будут храниться нужные записи, допустим в $array['Ukraine'][0] попадут: id3,id20, в $array['Ukraine'][1] попадут: id7,id14.


Даже можно было бы вообще сделать так (последнюю строчку)
$newarr[$country[1]][$temp] = $v; , то есть массив.


Написал где-то за 7-8 минут, ошибся лишь в 3-м аргументе для preg_match, мне показалось, что карман возвращает именно в 4-ый аргумент, а не в 3ий, но это легко проверяется одним запуском и заглянуть на php.net :)

Теперь все понятно?

Спустя 4 минуты, 52 секунды (15.09.2011 - 22:58) Семён написал(а):
Немного побыстрее: (2-ва прохода)
foreach($ar as $result) 
$tree[$result['c_name_eng']][$result['c_name_rus']] = $result['r_name_rus'];
ksort($tree);
foreach($tree as &$result)
ksort($result);

echo "<pre>";
print_r($tree);
echo "</pre>";

Спустя 1 минута, 30 секунд (15.09.2011 - 22:59) inpost написал(а):
DorianLeroy
"Прошу прощения, что не выложил задачу полностью в открытый доступ. Мне кажется это довольно конфидициальная инфа для той фирмы."
Да тут задачка на знания, уверен, что те, кто знают ответ, знали бы ответ и на собеседовании, а те, кто не знали, как решить, они бы всё равно не запомнили бы тут, как это решается. Так что на месте фирмы я бы не обижался. Сегодня все научатся, завтра отбор кандидатов будет куда более лучше, потому что все будут умные smile.gif
Жаль, что вторую задачку не показываешь smile.gif

Спустя 2 минуты, 43 секунды (15.09.2011 - 23:02) inpost написал(а):
Семён
Это ещё спорный вопрос, чей быстрее smile.gif

Спустя 51 секунда (15.09.2011 - 23:03) Семён написал(а):
Ээээ я не так понял) ща переделаю

Спустя 16 минут, 23 секунды (15.09.2011 - 23:19) killer8080 написал(а):
Цитата (DorianLeroy @ 15.09.2011 - 22:48)
там задача на час - первая часть выбрать из Mysql

тю, так я думал смысл в том чтоб показать работу с массивами. Если сам берёшь данные из бд, то и брать их нужно в том виде как надо, а так лишняя нагрузка на сервер, с ворочаньем массивов.

Спустя 24 минуты, 20 секунд (15.09.2011 - 23:44) inpost написал(а):
killer8080
Мне показалось, что это разные задачи вообще.

Спустя 10 минут, 16 секунд (15.09.2011 - 23:54) killer8080 написал(а):
inpost
я думал что по условию дан приведённый массив и нужно заданным образом вывести данные.
Но если сам формируешь этот массив, то можно нужно сортировку делать на стороне БД.
В общем надо увидеть реальное условие задачи.

Спустя 7 часов, 2 минуты, 18 секунд (16.09.2011 - 06:56) zvezda_t написал(а):
Блин... Вы такие умные!!! blink.gif
Что я тут делаю? ph34r.gif

ушла грустить...

Спустя 7 часов, 41 минута, 9 секунд (16.09.2011 - 14:37) inpost написал(а):
zvezda_t
Умнеешь с умными smile.gif

Спустя 9 минут, 41 секунда (16.09.2011 - 14:47) zvezda_t написал(а):
inpost, спасибо inpost, ты прелесть user posted image

Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.