Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Cортировка массивов по вложенным массивам 
:(
    Опции темы
flashaa
Дата 6.3.2008, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Есть массив.
У него много ключей, cреди них есть 3 ключа user, free, our
по которым массив должен быть отсортирован.
Первичная сортировка должна быть по ключу user, т.е. все элементы массива, где user = 1, идут вверх. 
Элементы, где user = 0 , идут вниз.
Вторичная сортировка по ключу free с аналогичной логикой. 
И третья сортировка должна быть как следуюет из логики по ключу our.
Как будут сортироваться элементы с одинаковыми значениями ключей, между собой - не имеет смысла.
Т.е. сначала элементы отсортировываются на 2 группы (user 1 - cверху, user 0 - снизу),
затем внутри каждой из групп происходит сортировка ещё на 2 группы   (free 1 - сверху, free 0 - снизу ).
Получает уже 4 группы. Затем происходит сортировка по 3 критерию внутри каждой из 4 групп их становится уже 8.

Как это лучше реализовать?
Вот так я реализовал деление на 2 первые группы:

Код

usort($res, create_function('$a, $b', 
                                 'if ($a["users"] > $b["users"]) return -1;
                                  if ($a["users"] < $b["users"]) return 1;
                                  if ($a["free"] < $b["free"]) return 1;
                                  if ($a["free"] > $b["free"]) return -1;
                                  if (($a["users"] == $b["users"]) || ($a["free"] > $b["free"])) return 0;'));

Уже чересчур громоздко, если добавить ещё 3 критерий, то условий будет намного больше.
В сортировке я малоопытен.

PM MAIL   Вверх
flashaa
Дата 6.3.2008, 11:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Немного запутано сказал.. Есть массив, в котором элементы - массивы с нескольким ключами
Код

array (
    array( [user] =>
              [free] =>
              [our] =>)

    array( [user] =>
              [free] =>
              [our] =>)

    array( [user] =>
              [free] =>
              [our] =>)
)


Вот в нем надо переставить внутренние array по описанному выше алгоритму.
PM MAIL   Вверх
flashaa
Дата 6.3.2008, 11:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Код

$max = 20;

for($i = 0; $i < $max; $i++) {
    
    $arr[$i] = array('1_user' => rand(0,1), '2_free' => rand(0,1), '3_our' => rand(0,1));
    
}

array_multisort($arr, SORT_DESC);
print_r($arr);


Код

Array
(
    [0] => Array
        (
            [1_user] => 1
            [2_free] => 1
            [3_our] => 1
        )

    [1] => Array
        (
            [1_user] => 1
            [2_free] => 1
            [3_our] => 1
        )

    [2] => Array
        (
            [1_user] => 1
            [2_free] => 1
            [3_our] => 0
        )

    [3] => Array
        (
            [1_user] => 1
            [2_free] => 1
            [3_our] => 0
        )

    [4] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 1
        )

    [5] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 1
        )

    [6] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 0
        )

    [7] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 0
        )

    [8] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 0
        )

    [9] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 0
        )

    [10] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 0
        )

    [11] => Array
        (
            [1_user] => 1
            [2_free] => 0
            [3_our] => 0
        )

    [12] => Array
        (
            [1_user] => 0
            [2_free] => 1
            [3_our] => 0
        )

    [13] => Array
        (
            [1_user] => 0
            [2_free] => 1
            [3_our] => 0
        )

    [14] => Array
        (
            [1_user] => 0
            [2_free] => 1
            [3_our] => 0
        )

    [15] => Array
        (
            [1_user] => 0
            [2_free] => 1
            [3_our] => 0
        )

    [16] => Array
        (
            [1_user] => 0
            [2_free] => 0
            [3_our] => 1
        )

    [17] => Array
        (
            [1_user] => 0
            [2_free] => 0
            [3_our] => 1
        )

    [18] => Array
        (
            [1_user] => 0
            [2_free] => 0
            [3_our] => 1
        )

    [19] => Array
        (
            [1_user] => 0
            [2_free] => 0
            [3_our] => 0
        )

)

Если сделать имена ключей по алфавиту в порядке убывания приоритета и использовать array_mulisort, то вроде сортировка правильная, только это установлено экспериментально. Что что скажет?
PM MAIL   Вверх
A1ekcandr
Дата 6.3.2008, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 99
Регистрация: 27.6.2007

Репутация: 1
Всего: 1



похоже ты сам ответил на свой вопрос smile
PM MAIL   Вверх
SelenIT
Дата 6.3.2008, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 32
Всего: 401



Хм... вроде логично (причем даже multisort избыточен - обычного sort должно хватить;), но настораживает, что для работоспособности этого шаманства важен алфавитный порядок ключей (по идее ведь, при сравнении массивов они и так ведь должны анализироваться в том порядке, в каком заданы). Вообще, имхо, сравнение массивов на "больше-меньше" - вещь слишком экзотическая, чтоб очень сильно на нее полагаться. По крайней мере, в мануале соотв. операторы явно не описаны (только "равно" и "не равно").

А поменять местами "строки" и "столбцы" массива никак нельзя (чтобы было 'user'=>array(1,0,0,1, ... ,0), 'free'=>(0,0,1,1, ..., 1) и т.д.)? И воспользоваться array_multisort штатным образом. И, кстати, откуда эти данные берутся - если из БД, нельзя ли получать их оттуда уже отсортированными как надо?

Это сообщение отредактировал(а) SelenIT - 6.3.2008, 13:16


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
flashaa
Дата 6.3.2008, 13:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



SelenIT
Цитата(SelenIT @  6.3.2008,  13:12 Найти цитируемый пост)
по идее ведь, при сравнении массивов они и так ведь должны анализироваться в том порядке, в каком заданы

Ключи добавляются в разном порядке, потому лучше назвать их алфавитно, затем сделать ksort();


Цитата(SelenIT @  6.3.2008,  13:12 Найти цитируемый пост)
По крайней мере, в мануале соотв. операторы явно не описаны (только "равно" и "не равно").

Непонял, почему сравнение МАССИВОВ ? Ведь сравниваются же ключи - скалярные выражения. Подобное сравнение происходит при работе функции array_multisort? Можно раскрыть тайну ее работы, потому что я ее так  и не знаю.
Данные генерируются в самой программе, так что вообщем-то можно поставить их в любом порядке. Только объясните, зачем? 
PM MAIL   Вверх
SelenIT
Дата 6.3.2008, 14:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 32
Всего: 401



Цитата(flashaa @  6.3.2008,  13:43 Найти цитируемый пост)
почему сравнение МАССИВОВ ?

Потому что элементы массива $arr, переданного аргументом в array_multisort, являются массивами smile. Они и сравниваются друг с другом - по правилам сравнения массивов, которые в мануале не описаны (по наблюдаемому поведению можно заключить, что элементы сравниваются попарно в порядке соответствующих ключей - в принципе, то, что надо, но полагаться на это как-то стрёмно;).


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
flashaa
Дата 6.3.2008, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



SelenIT, вы уверены что элементы сравниваются именно на больше/меньше/равно? По поводу стремности совершенно согласен. Если вдруг при составлении массива выскочило исключение, то один подмассив не достроился и сравнение с ним уже идет по-другому. Кстати он  оказался вообще в конце всех, хотя должен был иметь наивысший приоритет судя по ключу user.. Вы правы, но как более надежно сортировать?
PM MAIL   Вверх
SelenIT
Дата 6.3.2008, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 32
Всего: 401



Цитата(flashaa @  6.3.2008,  16:14 Найти цитируемый пост)
вы уверены что элементы сравниваются именно на больше/меньше/равно?

Конечно, как же иначе? Что еще может быть основание для порядка "убывает-возрастает"?
Цитата(flashaa @  6.3.2008,  16:14 Найти цитируемый пост)
как более надежно сортировать?

Либо "довести до ума" вариант с usort, для простоты не заморачиваясь с анонимной функцией (от явного создания ф-ции ничего не убудет, да и три вложенных условия - не такая уж большая сложность), либо "транспонировать" массив и использовать array_multisort обычным образом. Либо заполнять массив сразу в нужном порядке, используя по сути ту же ф-цию сравнения и array_splice. Других вариантов я не вижу...


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
SelenIT
Дата 6.3.2008, 17:26 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 32
Всего: 401



<self-moderated>была написана чушь - перепутал с JS smile</self-moderated>

Самый "лобовой" вариант ф-ции сравнения, проверенный:
Код

function cmp($a, $b) {
    if ($a['users'] != $b['users'])
        return $a['users'] > $b['users'] ? -1 : 1;
    elseif ($a['free'] != $b['free'])
        return $a['free'] > $b['free'] ? -1 : 1;
    elseif ($a['our'] != $b['our'])
        return $a['our'] > $b['our'] ? -1 : 1;
    else
        return 0;
}


Это сообщение отредактировал(а) SelenIT - 6.3.2008, 23:41


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
flashaa
Дата 10.3.2008, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



SelenIT, спасибо за помощь. Пока остановился на usort. Но если вдруг будут проблемы со стабильностью, использую ваше предложение.
PM MAIL   Вверх
SelenIT
Дата 10.3.2008, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

Репутация: 32
Всего: 401



Так функция выше для usort и предназначена. Проблем со стабильностью возникать не должно, вроде все ж явно предусмотрено... smile


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
flashaa
Дата 10.3.2008, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 796
Регистрация: 7.3.2006

Репутация: 19
Всего: 25



Цитата(SelenIT @  10.3.2008,  12:41 Найти цитируемый пост)
Так функция выше для usort и предназначена. 

Да я имел в виду простую сортировку без функции - sort.  smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0888 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.