Неправильно используемый array_multisort(), дающий правильный результат?

В настоящее время я касаюсь какого-то устаревшего кода в попытке очистить его и натолкнулся на что-то вроде загадки. Я не решаю даже отдаленно критически важную задачу, поэтому считаю, что это, по большей части, спортивный вопрос, но он все еще вызывает недоумение. Цвет мне любопытен.

Этот код:

// dummy data for the sake of testing / abstract visualisation;
// x is thrown in as an experiment:
$workTables = array(
    array('x' => 5, 'Name' => 'foo3', 'Update_time' => '2013-04-04 04:40',),
    array('x' => 4, 'Name' => 'foo4', 'Update_time' => '2013-04-01 04:40',),
    array('x' => 3, 'Name' => 'foo2', 'Update_time' => '2013-04-04 09:40',),
    array('x' => 2, 'Name' => 'foo1', 'Update_time' => '2013-04-12 04:40',),
    array('x' => 1, 'Name' => 'foo5', 'Update_time' => '2012-12-04 04:40',),
);

// original legacy code:
if (!empty($workTables)) {
    $sort = array();
    foreach ($workTables as $key => $value) {
        $sort[$key]["Update_time"] = $value["Update_time"];
    }
    array_multisort($workTables, SORT_ASC, SORT_STRING, $sort);
}

... при этом бросая двенадцать уведомлений (" Notice: Array to string conversion ... "), работает как положено, упорядочив все элементы в $workTables в соответствии с Update_time,

(Столбец "х" является частью моей попытки исключить, что он имеет какое-либо отношение к Name, который в исходном коде является фиксированным префиксом, за которым следует отметка времени (например, work_table_1367940392, work_table_1367940395...), делая сортировку по Name эквивалентно сортировке по Update_time.)

Очевидно, так как я не хочу программировать по совпадению, по крайней мере это будет заменено на:

// new code:
if (!empty($workTables)) {
    $sort = array();
    foreach ($workTables as $key => $value) {
        $sort[$key] = $value["Update_time"];
    }
    array_multisort($sort, SORT_ASC, SORT_STRING, $workTables);
}

... что соответствует описанию array_multisort() также делает то, что мы хотим, и не бросает уведомления в наше лицо.

Но что меня действительно интересует, так это почему старый код работает (несмотря на это).

Частичной причиной, по-видимому, является поведение asort() и со., которые имеют (частично) недокументированную особенность, что они могут работать с многомерными массивами, действуя в соответствии с содержимым массива, работая через структуру "слева направо" (по крайней мере, в PHP 5.4.7 (cli))... но... я застрял, пытаясь понять, что делает $workTables а также $sort " взаимозаменяемы ".

Я пытался взглянуть на исходный код PHP на C, чтобы понять это, но я застрял в попытке понять, что здесь происходит:

/* Do the actual sort magic - bada-bim, bada-boom. */
zend_qsort(indirect, array_size, sizeof(Bucket **), php_multisort_compare TSRMLS_CC);

... так как мои знания C ужасно заржавели и zend_qsort() Сам по себе просто из моей лиги.

Любой берущий?

Имейте в виду, я не отчаянно нуждаюсь в ответе, так что не тратьте слишком много времени на это, но, возможно, кому-то тоже нравится головоломка?:)

Лично я потратил некоторое время на это исключительно потому, что предпочитаю тщательно разбираться в коде, особенно когда пытаюсь его очистить - даже если он работает только по стечению обстоятельств. Я только что зашел в тупик, когда дело доходит до дальнейшего понимания, так что переполнение стека кажется лучшим шансом для дальнейшего просвещения.

Итак, если у вас есть представление о том, что происходит за кулисами (я подозреваю, что это что-то тривиальное, что я упустил из виду; как правило, это моя проблема после того, как я некоторое время хожу по кругу), я хотел бы услышать это!:)

1 ответ

Насколько я понимаю, массив создается и хранится в $sort[$key], Затем, как только вы позвоните array_multisort() бывает так, что массив преобразуется обратно в строку и сортируется с использованием этой строки в качестве значения, определяющего порядок - как сказано в предупреждении. Затем эта строка используется в качестве значения, определяющего порядок.

Как выполняется преобразование массива-> строка? Просто делаю echo $anArrayValueHere; не полезно; распечатывает Array, Подобный трюк, echo "" . $anArrayValueHere . ""; также не дает ничего полезного. (Но при этом это не приводит к уведомлению!)

Вполне возможно, что serialize() используется. Исходя из этого, давайте посмотрим, что будет использоваться в качестве значения, определяющего порядок:

#!/usr/bin/php5
<?php
$sort[0]["Update_time"] = '2012-12-04 04:40';
echo serialize($sort[0]);

затем

$ ./php tmp.php
a:1:{s:11:"Update_time";s:16:"2012-12-04 04:40";}

Похоже, что ключ был бы достаточно определенным, чтобы дать что-то полезное для определения порядка сортировки так же, как и просто Update_time значение будет.

Я не уверен что serialize() используется, но если это так, я думаю, что это объяснение.

Другие вопросы по тегам