dtkf64283 2018-04-16 22:53
浏览 54
已采纳

按非字母,用户定义的字符串值对数组进行排序

I want to sort an array in a complicated way and am not sure how to go about it. Here is a rough idea of the data I'm working with:

[
  { target: random.text.cpu-pct-0, otherData[...] },
  { target: random.text.cpu-pct-1, otherData[...] },
  { target: random.text.cpu-pct-2, otherData[...] },
  { target: random.text.example-0, otherData[...] },
  { target: random.text.example-1, otherData[...] },
  { target: random.text.memory, otherData[...] },
  ...
]

I want all the objects with a target that includes the string cpu-pct to come first, then the objects with a target that includes the string memory, then example. This array could have any number of items, so re-sorting by index won't work. There could be 1 object with a target that includes cpu-pct, or there could be 50+. Same goes for the other strings I'm sorting by.

I thought about looping over the original array, checking if the desired string exists, saving the matching objects to new arrays for each target I'm looking for, then merging the arrays at the end. I think that would work, but I'd imagine there is a better, more efficient solution, probably using usort, but I'm at a loss. Any ideas?

  • 写回答

2条回答 默认 最新

  • dtstnjl898781429 2018-04-16 23:17
    关注

    usort is definitely the way to go. Here's a fairly generalised way of doing it, you can expand the $ranks array to include other terms to sort against if you like.

    $a = json_decode('[
      { "target": "random.text.cpu-pct-0", "otherData": [1, 2, 3] },
      { "target": "random.text.cpu-pct-1", "otherData": [2, 2, 3] },
      { "target": "random.text.cpu-pct-2", "otherData": [3, 2, 3] },
      { "target": "random.text.example-0", "otherData": [4, 2, 3] },
      { "target": "random.text.example-1", "otherData": [5, 2, 3] },
      { "target": "random.text.memory", "otherData": [6, 2, 3] } ]');
    
    $ranks = array('example' => 0, 'memory' => 1, 'cpu-pct' => 2);
    
    function rank($obj) {
        global $ranks;
    
        foreach ($ranks as $key => $value) {
            if (strpos($obj->target, $key) !== false) return $value;
        }
        // sort anything that doesn't match last
        return -1;
    }
    
    function cmp($a, $b) {
        return rank($b) - rank($a);
    }
    
    usort($a, "cmp");
    
    print_r($a);
    

    Output:

    Array
    (
        [0] => stdClass Object
            (
                [target] => random.text.cpu-pct-0
                [otherData] => Array
                    (
                        [0] => 1
                        [1] => 2
                        [2] => 3
                    )
    
            )
    
        [1] => stdClass Object
            (
                [target] => random.text.cpu-pct-1
                [otherData] => Array
                    (
                        [0] => 2
                        [1] => 2
                        [2] => 3
                    )
    
            )
    
        [2] => stdClass Object
            (
                [target] => random.text.cpu-pct-2
                [otherData] => Array
                    (
                        [0] => 3
                        [1] => 2
                        [2] => 3
                    )
    
            )
    
        [3] => stdClass Object
            (
                [target] => random.text.memory
                [otherData] => Array
                    (
                        [0] => 6
                        [1] => 2
                        [2] => 3
                    )
    
            )
    
        [4] => stdClass Object
            (
                [target] => random.text.example-0
                [otherData] => Array
                    (
                        [0] => 4
                        [1] => 2
                        [2] => 3
                    )
    
            )
    
        [5] => stdClass Object
            (
                [target] => random.text.example-1
                [otherData] => Array
                    (
                        [0] => 5
                        [1] => 2
                        [2] => 3
                    )
    
            )
    
    )
    

    If you want to further sort on the value after the keyword, you could append that to the ranking value and then sort on the combined value e.g.

    $ranks = array('cpu-pct', 'memory', 'example');
    
    function rank($obj) {
        global $ranks;
    
        foreach ($ranks as $key => $value) {
            if (preg_match("/$value(.*)$/", $obj->target, $matches))
                return $key . $matches[1];
        }
        // sort anything that doesn't match last
        return 'z';
    }
    
    function cmp($a, $b) {
        return strcmp(rank($a), rank($b));
    }
    
    usort($a, "cmp");
    

    If you had more than 10 strings to sort by, you would need to change the return value from rank to sprintf('%02d', $key) . $matches[1] to ensure sorting worked properly (replace 02 with as many digits as necessary to ensure you can represent all the sort strings in that many digits).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 乘性高斯噪声在深度学习网络中的应用
  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥30 python代码,帮调试,帮帮忙吧