【问题标题】:php sort multidimentional array by custom orderphp按自定义顺序对多维数组进行排序
【发布时间】:2014-04-01 10:06:52
【问题描述】:

按其键值(asc 或 desc)之一对多维数组进行排序的请求次数过多。 但我没有找到任何解决方案来解决我的问题,您必须按预定义的自定义顺序按其键值之一对多维数组进行排序。

以数组为例

$array[0] = array('id'=> '111', value=>'abc');
$array[1] = array('id'=> '100', value=>'abc');
$array[2] = array('id'=> '132', value=>'abc');
$array[3] = array('id'=> '222', value=>'abc');
$array[4] = array('id'=> '112', value=>'abc');
$array[5] = array('id'=> '200', value=>'abc');

并按照下面数组中定义的顺序按子键“id”对该数组进行排序:

$sort_order_id = array('112','111','132','100');

所以结果是

$array[0] = array('id'=> '112', value=>'abc');
$array[1] = array('id'=> '111', value=>'abc');
$array[2] = array('id'=> '132', value=>'abc');
$array[3] = array('id'=> '100', value=>'abc');
$array[4] = array('id'=> '222', value=>'abc');
$array[5] = array('id'=> '200', value=>'abc');

注意:如果某些 id 在 $sort_order_id 数组中不可用,请将它们放在最后(如上例中,id 222 和 200 不在 $sort_order_id 数组中,因此它按照之前的顺序排在最后顺序)

我尝试了很多,但无法为此创建算法...我希望有人能帮助我...

【问题讨论】:

  • 你试过我的答案了吗?
  • 为什么要投反对票?请解释...这个问题以前从未在任何社区提出过
  • @SatishSharma ,上面的问题略有不同,因为如果子键 id 不在排序顺序中,它就不会处理。正确阅读我的问题。

标签: php arrays sorting multidimensional-array


【解决方案1】:

id对数组排序的标准代码:

usort($data, function($x, $y) { return $x['id'] - $y['id']; });

您想要做的不是按 id 本身排序,而是按每个 id 的“权重”(表示您希望 id 放入的任意顺序)。所以创建一个数组,其中键是 id,值是权重,并使用它将 id 转换为权重:

// array_flip turns 0 => 112, 1 => 111, ... into 122 => 0, 111 => 1, ...
$weights = array_flip(array('112','111','132','100'));

usort($data, function($x, $y) use($weights) {
    return $weights[$x['id']] - $weights[$y['id']];
});

更新:由于您还想处理没有指定权重的 id,您将不得不进一步扩展上述内容:

usort($data, function($x, $y) use($weights) {
    if (!isset($weights[$x['id']], $weights[$y['id']])) {
        // none of the ids have weight, so sort by bare id
        return $x['id'] - $y['id'];
    }
    else if (!isset($weights[$x['id']])) { 
        // x does not have weight, put it last
        return 1;
    }
    else if (!isset($weights[$y['id']])) {
        // y does not have weight, put it last
        return -1;
    }

    // both have weights, use them
    return $weights[$x['id']] - $weights[$y['id']];
});

【讨论】:

  • 被接受为答案,因为它比其他人更快。谢谢...替换行 if (!isset($weights[$x['id']], $weights[$y['id']])) { 用 if (!isset($weights[$x[ 'id']]) && !isset($weights[$y['id']])) {
【解决方案2】:

您需要usort(),它允许您按定制要求进行排序。在您的情况下,您需要按 ID 在您的 sort_order_id 数组中的位置进行排序。

$array = array(
    array('id'=> '111', value=>'abc'),
    array('id'=> '100', value=>'abc'),
    array('id'=> '132', value=>'abc'),
    array('id'=> '112', value=>'abc')
);
$sort_order_id = array('112','111','132','100');
usort($array, function($a, $b) {
    global $sort_order_id;
    return array_search($a['id'], $sort_order_id) - array_search($b['id'], $sort_order_id);
});

【讨论】:

  • 在排序之前翻转排序顺序数组将允许您将 O(n) array_search 替换为 O(1) 数组查找,从而可能使排序速度更快。
【解决方案3】:

试试这个

echo "<pre>";

$array[0] = array('id'=> '111', 'value'=>'abc');
$array[1] = array('id'=> '100', 'value'=>'abc');
$array[2] = array('id'=> '132', 'value'=>'abc');
$array[3] = array('id'=> '222', 'value'=>'abc');
$array[4] = array('id'=> '112', 'value'=>'abc');
$array[5] = array('id'=> '200', 'value'=>'abc');

$arr_temp = $array;
$array = array();
$sort_order_id = array('112','111','132','100');
foreach($sort_order_id as $order_id)
{
    foreach($arr_temp as $key=>$arr)
    {
        if($arr['id'] == $order_id)
        {
            $array[] = $arr;
            unset($arr_temp[$key]);
        }
    }
}

foreach($arr_temp as $key=>$arr)
{
        $array[] = $arr;
        unset($arr_temp[$key]);
}

print_r($array);

输出:

Array
(
    [0] => Array
        (
            [id] => 112
            [value] => abc
        )

    [1] => Array
        (
            [id] => 111
            [value] => abc
        )

    [2] => Array
        (
            [id] => 132
            [value] => abc
        )

    [3] => Array
        (
            [id] => 100
            [value] => abc
        )

    [4] => Array
        (
            [id] => 222
            [value] => abc
        )

    [5] => Array
        (
            [id] => 200
            [value] => abc
        )

)

【讨论】:

  • 这将尽可能慢。您实际上是在使用不必要的高常数系数进行selection sort
【解决方案4】:

@Jon 的答案可以使用 spaceship 运算符和空值合并更加简洁。

id 排序数组一旦翻转就变成了一个方便的查找。 如果在排序数组中找不到给定行的 id 值,则将其“稍后”推送到输出数组中。

代码:(Demo)

$array = [
    ['id' => '111', 'value' => 'abc'],
    ['id' => '100', 'value' => 'abc'],
    ['id' => '132', 'value' => 'abc'],
    ['id' => '222', 'value' => 'abc'],
    ['id' => '112', 'value' => 'abc'],
    ['id' => '200', 'value' => 'abc']
];

$idPriorities = array_flip(['112', '111', '132', '100']);
$idOutlier = count($idPriorities);

usort(
    $array,
    function($a, $b) use ($idPriorities, $idOutlier) {
        return ($idPriorities[$a['id']] ?? $idOutlier) <=> ($idPriorities[$b['id']] ?? $idOutlier);
    }
);

var_export($array);

或使用 PHP7.4+ (Demo)

usort(
    $array,
    fn($a, $b) => ($idPriorities[$a['id']] ?? $idOutlier) <=> ($idPriorities[$b['id']] ?? $idOutlier)
);

【讨论】:

    猜你喜欢
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多