排序多维数组:对列包含子字符串进行优先排序,然后按第二列排序

我目前正在创建一种排序方法,该方法由mysql查询的值组成。

这是数组的简要视图:

    Array

(

[0] => Array

(

['id'] = 1;

['countries'] = 'EN,CH,SP';

)

[1] => Array

(

['id'] = 2;

['countries'] = 'GE,SP,SV';

)

)

我已经成功地基于数字id值进行了正常的排序,但是我想按“国家/地区”字段的内容对数组进行排序(如果在这种情况下包含设置的字符串和国家/地区代码),然后通过id字段。

以下代码段是我的第一个想法,但我不知道如何将其合并到工作功能中:

in_array('EN', explode(",",$a['countries']) );

你会怎么做?

谢谢!


不幸的是,我真的一无所获。

这是我目前拥有的东西,它给我的只有错误: uasort() [function.uasort]: Invalid comparison function

function compare($a, $b) {

global $usercountry;

if ( in_array($usercountry, $a['countries']) && in_array($usercountry, $a['countries']) ) {

$return = 0;

}

else if (in_array($usercountry, $a['countries'])) {

$return = 1;

}

else {

$return = -1;

}

return $return;

}

$array= usort($array, "compare");

有谁可以给​​我提示如何进行操作吗?

回答:

我个人将与结合使用自定义(匿名)函数usort()

编辑:重新-您的评论。希望这将使您走上正确的道路。此功能为同时具有EN或都不具有EN的元素赋予相同的优先级,或者当仅具有EN的元素具有调整后的优先级。

usort($array,function ($a, $b) {

$ac = strpos($a['countries'],'EN');

$bc = strpos($b['countries'],'EN');

if (($ac !== false && $bc !== false) || ($ac == false && $bc == false)) {

return 0;

}

elseif ($ac !== false) {

return 1;

}

else {

return -1;

}

});

另一方面,如果两个函数都具有EN,则该函数具有相同的优先级;如果一个函数具有EN,则该函数具有较高的优先级;如果两个都不具有EN,则进行文本比较。

usort($array,function ($a, $b) {

$ac = strpos($a['countries'],'EN');

$bc = strpos($b['countries'],'EN');

if ($ac !== false && $bc !== false)) {

return 0;

}

elseif ($ac !== false) {

return 1;

}

elseif ($bc !== false) {

return -1;

}

else {

if ($a['countries'] == $b['countries']) {

return 0;

}

elseif($a['countries'] > $b['countries']) {

return 1;

}

else {

return -1;

}

}

});

再次,希望这将给您足够的指导,以自己前进。如果您有任何问题,请随时发表更多评论,我将尽力提供帮助。

如果您想将多个属性与重量进行比较,请注意:尝试使用时髦的开关块,例如

$ac = array_flip(explode(',',$a['countries']));

$bc = array_flip(explode(',',$b['countries']));

switch (true) {

case array_key_exists('EN',$ac) && !array_key_exists('EN',$bc):

return 1;

case array_key_exists('DE',$ac) && !array_key_exists('EN',$bc) && !array_key_exists('EN',$bc):

return 1;

// and so on

}

更多编辑!

实际上,我在考虑复杂排序的问题,我想出了以下解决方案供您考虑。它将允许您根据出现在国家/地区索引中的关键字定义数字排名。这是代码,包括一个示例:

$array = array(

array(

'countries' => 'EN,DE,SP',

),

array(

'countries' => 'EN,CH,SP',

),

array(

'countries' => 'DE,SP,CH',

),

array(

'countries' => 'DE,SV,SP',

),

array(

'countries' => 'EN,SP,FR',

),

array(

'countries' => 'DE,FR,CH',

),

array(

'countries' => 'CH,EN,SP',

),

);

$rankings = array(

'EN' => 10,

'SP' => 8,

'FR' => 7,

'DE' => 5,

'CH' => 3,

'SV' => 1,

);

usort($array, function (&$a, &$b) use ($rankings) {

if (isset($a['_score'])) {

$aScore = $a['_score'];

}

else {

$aScore = 0;

$aCountries = explode(',',$a['countries']);

foreach ($aCountries as $country) {

if (isset($rankings[$country])) {

$aScore += $rankings[$country];

}

}

$a['_score'] = $aScore;

}

if (isset($b['_score'])) {

$bScore = $b['_score'];

}

else {

$bScore = 0;

$bCountries = explode(',',$b['countries']);

foreach ($bCountries as $country) {

if (isset($rankings[$country])) {

$bScore += $rankings[$country];

}

}

$b['_score'] = $bScore;

}

if ($aScore == $bScore) {

return 0;

}

elseif ($aScore > $bScore) {

return -1;

}

else {

return 1;

}

});

注意:此代码会将排序 。如果您想要反向行为,请更改此:

    elseif ($aScore > $bScore) {

    elseif ($aScore < $bScore) {

请注意,大于符号已更改为小于符号。进行此更改将导致 。希望所有这些都对您有所帮助!

回答:

此代码将对您的数组进行一些小的更改,因为它将_score元素添加到每个数组。希望这不是问题,因为通过存储该值,我确实能够使速度提高两倍以上(在我的基准测试中,.00038-.00041降至.00016-.00018)。如果不是,请删除if检索缓存值的块,并让else块的内容每次执行,当然存储分数值的部分除外。

顺便说一下,这是var_export()数组排序后的转储:

array (

0 => array (

'countries' => 'EN,SP,FR',

'_score' => 25,

),

1 => array (

'countries' => 'EN,DE,SP',

'_score' => 23,

),

2 => array (

'countries' => 'EN,CH,SP',

'_score' => 21,

),

3 => array (

'countries' => 'CH,EN,SP',

'_score' => 21,

),

4 => array (

'countries' => 'DE,SP,CH',

'_score' => 16,

),

5 => array (

'countries' => 'DE,FR,CH',

'_score' => 15,

),

6 => array (

'countries' => 'DE,SV,SP',

'_score' => 14,

),

)

请享用!

以上是 排序多维数组:对列包含子字符串进行优先排序,然后按第二列排序 的全部内容, 来源链接: utcz.com/qa/409844.html

回到顶部