Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Сортировка ассоциативного массива

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
Daxe_rag
Отправлено: 24 Сентября, 2017 - 16:29:59
Post Id


Новичок


Покинул форум
Сообщений всего: 2
Дата рег-ции: Сент. 2017  


Помог: 0 раз(а)




Доброго дня!

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

Мне пришло в голову единственное решение:

PHP:
скопировать код в буфер обмена
  1.  
  2. $names = array("Jhon" => array("status" => "working", "id" => "21", "param" => "8"),
  3. "Mike" => array("status" => "working", "id" => "10", "param" => "4"),
  4. "Nill" => array("status" => "fired", "id" => "4", "param" => "3"),
  5. "Tom" => array("status" => "working", "id" => "2", "param" => "12"),
  6. "Jake" => array("status" => "fired", "id" => "88", "param" => "3"));
  7.         for ($i=0; $i<count($names); $i++){
  8.                 for (reset($names); next($names)!=false; next($names)) {
  9.                         $key_next=key($names);
  10.                         prev($names);
  11.                         $key_curr=key($names);
  12.                         if ($names[$key_curr]['param']>$names[$key_next]['param']){
  13.                                 $temp=$names[$key_curr];
  14.                                 $names[$key_curr]=$names[$key_next];
  15.                                 $names[$key_next]=$temp;
  16.                         }
  17.                 }
  18.         }
  19. print_r($names);
  20.  


Отсортировать массив требовалось по возрастанию элемента "Param".

Честно говоря, интуитивно, мне такой способ сортировки кажется немного "кривоватым". Отсюда такой вопрос: какими еще способами можно отстортировать ассоциативный массив, разумеется не используя готовых функций?
 
 Top
Строитель Модератор
Отправлено: 24 Сентября, 2017 - 19:57:43
Post Id



Участник


Покинул форум
Сообщений всего: 1580
Дата рег-ции: Февр. 2014  
Откуда: Украина


Помог: 73 раз(а)




Daxe_rag, у вас ведь на выходе данные не верны.
 
 Top
Bio man
Отправлено: 24 Сентября, 2017 - 20:05:11
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2751
Дата рег-ции: Июль 2010  
Откуда: Даугавпилс, Латвия


Помог: 52 раз(а)




Откопал в лабараторках оптимизированный пузырьковый метод и переписал на PHP
PHP:
скопировать код в буфер обмена
  1.  
  2. $names = [
  3.     "Jhon" => [
  4.         "status" => "working",
  5.         "id" => "21",
  6.         "param" => "8",
  7.     ],
  8.     "Mike" => [
  9.         "status" => "working",
  10.         "id" => "10",
  11.         "param" => "4",
  12.     ],
  13.     "Nill" => [
  14.         "status" => "fired",
  15.         "id" => "4",
  16.         "param" => "3",
  17.     ],
  18.     "Tom" => [
  19.         "status" => "working",
  20.         "id" => "2",
  21.         "param" => "12",
  22.     ],
  23.     "Jake" => [
  24.         "status" => "fired",
  25.         "id" => "88",
  26.         "param" => "3",
  27.     ],
  28. ];
  29.  
  30. function mySort(array $array, string $direction = 'asc'): array
  31. {
  32.     $keys = array_keys($array);
  33.     $values = array_values($array);
  34.    
  35.     $length = count($array);
  36.     $tailIndex = $length - 2;
  37.    
  38.     for ($i = 0; $i < $length; $i++) {
  39.         $changed = false;
  40.        
  41.         for ($j = 0, $endIndex = $tailIndex; $j <= $endIndex; $j++) {
  42.             if (
  43.                 ($direction === 'asc' && $values[$j]['param'] > $values[$j + 1]['param']) ||
  44.                 ($direction === 'desc' && $values[$j]['param'] < $values[$j + 1]['param'])
  45.             ) {
  46.                 $temp = $values[$j];
  47.                 $values[$j] = $values[$j + 1];
  48.                 $values[$j + 1] = $temp;
  49.                
  50.                 $temp = $keys[$j];
  51.                 $keys[$j] = $keys[$j + 1];
  52.                 $keys[$j + 1] = $temp;
  53.                
  54.                 $changed = true;
  55.                 $tailIndex = $j;
  56.             }
  57.         }
  58.        
  59.         if (!$changed) {
  60.             break;
  61.         }
  62.     }
  63.    
  64.     return array_combine($keys, $values);
  65. }
  66.  
  67. var_dump(mySort($names));
  68.  


Если интересно, могу скинуть все сортировщики написанные на C++ (можно скомпилить в VS2015), там есть
Quick Sort, Selection Sort, и множество алгоритмов сортировки Шелла.
К тому-же пргграммка делает замеры эффективности по времени, и количество перестановок и сравнений.
 
 Top
Строитель Модератор
Отправлено: 24 Сентября, 2017 - 20:12:35
Post Id



Участник


Покинул форум
Сообщений всего: 1580
Дата рег-ции: Февр. 2014  
Откуда: Украина


Помог: 73 раз(а)




Daxe_rag, один из вариантов:
Спойлер (Отобразить)
 
 Top
Daxe_rag
Отправлено: 04 Октября, 2017 - 03:09:23
Post Id


Новичок


Покинул форум
Сообщений всего: 2
Дата рег-ции: Сент. 2017  


Помог: 0 раз(а)




[quote=Строитель]Daxe_rag

У вас получается не совсем правильно. Если сортировать массив из моего примера, то он отсортируется корректно, но если заменить, например, последнее значение "param" на 4, то есть меньше максимального, записанного в $values, но больше первого элемента, то функция запишет этот ключ как первый.
(Добавление)
Спасибо за ответы. Если кому-то вдруг понадобится, вот рабочий код сортировки:
PHP:
скопировать код в буфер обмена
  1.  
  2. $names = array("Jhon" => array("status" => "working", "id" => "21", "param" => "8"),
  3. "Mike" => array("status" => "working", "id" => "10", "param" => "4"),
  4. "Nill" => array("status" => "fired", "id" => "4", "param" => "3"),
  5. "Tom" => array("status" => "working", "id" => "2", "param" => "12"),
  6. "Jake" => array("status" => "fired", "id" => "88", "param" => "3"));
  7. function work_var1(&$names, $parametr){
  8.                 for ($j=0; $j<count($names); $j++){
  9.                         reset($names);
  10.                         for ($i=0; $i<count($names); $i++){
  11.                                 $key_curr=key($names);
  12.                                 next($names);
  13.                                 $key_next=key($names);
  14.                                 if ($names[$key_curr][$parametr]>$names[$key_next][$parametr]){
  15.                                         $temp=$names[$key_curr];
  16.                                         unset($names[$key_curr]);
  17.                                         $names[$key_curr]=$temp;
  18.                                         reset($names);                         
  19.                                 }
  20.                         }
  21.                 }
  22. }
  23. work_var1($names, "param");
  24.  

(Отредактировано автором: 04 Октября, 2017 - 03:33:30)

 
 Top
MouseZver
Отправлено: 04 Октября, 2017 - 12:52:52
Post Id



Новичок


Покинул форум
Сообщений всего: 58
Дата рег-ции: Июнь 2017  
Откуда: php.ru


Помог: 1 раз(а)




не используйте count внутри цикла for = ибо говнокод
не используйте for для перебора массива , для этого есть foreach = ибо говнокод
 
 Top
Строитель Модератор
Отправлено: 04 Октября, 2017 - 19:01:44
Post Id



Участник


Покинул форум
Сообщений всего: 1580
Дата рег-ции: Февр. 2014  
Откуда: Украина


Помог: 73 раз(а)




MouseZver пишет:
не используйте count внутри цикла for = ибо говнокод
Спорный вопрос (цитата):

Перебор массивов как показано ниже - это обычное дело для многих пользователей.
Спойлер (Отобразить)
Вышеприведенный код может работать медленно, так как размер массива вычисляется в каждой итерации. Поскольку размер не меняется, цикл может быть легко оптимизирован с помощью промежуточной переменной, в которую будет записан размер массива, вместо повторяющихся вызовов функции count():
Спойлер (Отобразить)
 
 Top
MouseZver
Отправлено: 24 Ноября, 2017 - 16:36:50
Post Id



Новичок


Покинул форум
Сообщений всего: 58
Дата рег-ции: Июнь 2017  
Откуда: php.ru


Помог: 1 раз(а)




Строитель пишет:
в которую будет записан размер массива, вместо повторяющихся вызовов функции count():

COUNT внутри фор каждый раз юзается при новом цикле. Это давно всем должно быть понятно
(Добавление)
и зачем вовсе пихать во фор ...
 
 Top
Строитель Модератор
Отправлено: 24 Ноября, 2017 - 16:42:53
Post Id



Участник


Покинул форум
Сообщений всего: 1580
Дата рег-ции: Февр. 2014  
Откуда: Украина


Помог: 73 раз(а)




MouseZver пишет:
COUNT внутри фор каждый раз юзается при новом цикле. Это давно всем должно быть понятно
Присмотритесь к этим двум примерам по-внимательнее, а если не увидите разницы - задайте вопрос.

UPD: Поясняющий пример:
Спойлер (Отобразить)
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB