错误地使用array_multisort()给出正确的结果?

问题描述:

我目前正在触摸一些遗留代码,试图清理它并遇到了一些难题。 我解决这个问题甚至不是关键任务,所以最多只考虑一个运动问题,但它仍然令我困惑。让我好奇。错误地使用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); 
} 

...当投掷12个通知( “Notice: Array to string conversion ...”),作品预期,通过根据Update_time订货在$workTables所有元素。

(的“x”列是我的企图排除它有什么关系Name,这在原代码是一个固定的前缀,后跟一个时间戳的一部分(例如work_table_1367940392work_table_1367940395,...) ,使得通过Name相当于排序,以通过排序Update_time

很明显,因为I don't want to program by coincidence,这是怎么回事最起码要替换为:

// 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(),做我们想要的,并不会在我们的脸上扔Notices。

但我真正感兴趣的是为什么旧代码的作品(尽管有通知)。

的部分原因似乎是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()本身就是刚刚脱离我的联盟。

任何接受者?

请记住,我不是绝望的答案,所以不要沉溺于此太多时间,但也许别人也喜欢一个谜题? :)

就我个人而言,我已经投入了一些时间,因为我更喜欢彻底理解代码,尤其是当我试图清理它时 - 即使它只是巧合运行的代码。当谈到进一步理解时,我刚刚达到了死胡同,所以*似乎是进一步启发的最佳机会。因此,如果你对幕后发生的事情有一个想法(我怀疑这是微不足道的事情,但我忽略了这一点;在我回过头一段时间后,这往往是我的问题),我很乐意听到!:)

+0

bada-bim,bada-boom的评论真的给了它。 – raidenace 2013-05-07 16:20:21

+0

@Raidenace:哈哈,我知道,对吗?它解释了*一切*。 :)(公平地说,我认为这是伟大的 - 幽默的评论是一种罕见的(如果含糊不清)高兴看到。) – pinkgothic 2013-05-08 07:15:10

据我所知,阵列正在创建和存储在$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(),但如果是,我认为这是解释。

+0

嗯,我没有看到任何'serialize()'的证据(这将是奇怪的'serialize()'抛出转换警告),但是......这也可能是由于我在C代码中完全迷失方向。 :)我相当确定排序本身是由于sort()和co的多维数组处理('sort()'也使用'zend_qsort()'),对我而言,这个奇怪的问题仍然是阵列。 – pinkgothic 2013-05-08 07:22:58

+0

“(但是它们都没有发出通知!)”顺便说一下,在我的机器上并不是这样,但这只是完成的一个旁注。不过,我得说,非常感谢你的刺伤! :)我希望我有不止一个upvote给你。 – pinkgothic 2013-05-08 07:25:01