排序多维数组:对列是否包含子字符串进行优先排序,然后按第二列排序 [英] Sorting multidim array: prioritize if column contains substring, then order by a second column

查看:89
本文介绍了排序多维数组:对列是否包含子字符串进行优先排序,然后按第二列排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am currently creating a sorting method that consists of values from an mysql query.

这是该数组的简要视图:

Here's a brief view of the array:

    Array
    (
        [0] => Array
            (
                ['id'] = 1;
                ['countries'] = 'EN,CH,SP';
            )
        [1] => Array
            (
                ['id'] = 2;
                ['countries'] = 'GE,SP,SV';
            )
    )

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

I have succeeded in making a normal usort based on the numeric id values, but I rather want to sort the array by the content of the "countries" field (if it contains a set string, a country code in this case), and then by the id field.

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

The following snippet was my first idea of how to do it, but I have no idea of how to incorporate it into an working function:

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

你会怎么做?

谢谢!

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

I am really getting nowhere with this unfortunately.

这是我目前拥有的东西,除了错误以外,它什么也没有给我:uasort() [function.uasort]: Invalid comparison function

Here is what I have for the moment, and its giving me nothing but errors: 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");

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

Is there anyone who might give me a hint of how to go on with it?

推荐答案

我个人将与

Personally, I would use a custom (anonymous) function in conjunction with usort().

重新-您的评论.希望这将使您走上正确的道路.此功能将同时具有EN或都不具有EN的元素给予同等的优先级,或者当仅具有EN的元素具有经过调整的优先级.

Re - your comment. Hopefully this will put you on the right track. This function gives equal priority to elements which both have EN or neither have EN, or adjusted priority when just one has 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,则进行文本比较.

This function, on the other hand, gives equal priority if both have EN, higher if one has EN, and does a text comparison if neither has 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;
        }
    }
});

再次,希望这会给您足够的指导,让您自己继续前进.如果您有任何问题,请随时发表更多评论,我将尽力提供帮助. 如果您想将多个属性与重量进行比较,请注意:尝试使用一个时髦的开关块,例如

Again, hopefully this will give you enough direction to move forward on your own. If you are having any problems, feel free to post more comments and I'll try to help. A note if you're tying to compare multiple properties with weight: try out a funky switch block, e.g.

$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
}

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

Actually, I was thinking more on the problem of complex sorting, and I have come up with the following solution, for your consideration. It will allow you to define numerical rankings based on keywords which would appear in the countries index. Here is the code, including an example:

示例数组

$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;
    }
});

注意:此代码会将排名最高的整体排序到数组顶部.如果您想要反向行为,请更改此:

Note: This code will sort the highest ranking entires to the top of the array. If you want reverse behavior, change this:

    elseif ($aScore > $bScore) {

    elseif ($aScore < $bScore) {

请注意,大于符号已更改为小于符号.进行此更改将导致最低排名的条目排在数组顶部.希望所有这些都对您有帮助!

Note that the greater-than was changed to a less-than symbol. Making this change will result in the lowest ranking entries being sorted to the top of the array. Hope all this helps!

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

This code will make a small change to your array, in that it adds the _score element to each array. Hopefully this is not a problem, as by storing this value I was literally able to increase speed by more than double (.00038-.00041 down to .00016-.00018 in my benchmarks). If not, remove the if blocks that retrieve the cached value and let the contents of the else blocks execute every time, except of course for the part which stores the score value.

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

By the way, here's a var_export() dump of the array after it was sorted:

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,
  ),
)

享受!

这篇关于排序多维数组:对列是否包含子字符串进行优先排序,然后按第二列排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆