Php 按预定义的值映射对对象数组进行排序

Php 按预定义的值映射对对象数组进行排序,php,arrays,sorting,multidimensional-array,stack,Php,Arrays,Sorting,Multidimensional Array,Stack,我有以下阵列: $inputArray = Array( [0] => stdClass Object ( [id] => 8 ) [1] => stdClass Object ( [id] => 7 ) [2] => stdClass Object ( [id] => 5 ) ) $sortingArray = [5,8,1] 我正在寻找一种通过id“值映

我有以下阵列:

$inputArray = Array(
    [0] => stdClass Object (
        [id] => 8
    )

    [1] => stdClass Object (
        [id] => 7
    )

    [2] => stdClass Object (
        [id] => 5
    )
)

$sortingArray = [5,8,1]
我正在寻找一种通过id“值映射”对输入数组进行排序的有效方法。。预期输出应为$inputArray,重新排序,以便第三项为第一项,第一项为第二项,以此类推


谢谢

您可以使用
array\u flip
创建临时数组。这将翻转数组,意味着值将是键

使用
usort
对数组进行排序

$tempArr = array_flip( $sortingArray  );
usort($inputArray, function($a, $b) use ( $tempArr ) {
    $tempA = isset( $tempArr[ $a->id ] ) ? $tempArr[ $a->id ] : 999999; //If id does not exist on $sortingArray. Use 999999 as an index
    $tempB = isset( $tempArr[ $b->id ] ) ? $tempArr[ $b->id ] : 999999;
    return $tempA - $tempB;
});

echo "<pre>";
print_r( $inputArray );
echo "</pre>";

我在这里使用了一些东西,主要的是我使用排序数组作为
array\u replace()
的目标,并使用
array\u column()
来索引对象(这需要PHP7.0+来处理对象)


array\u filter()
将删除不在输入数组中但在排序数组中的所有元素。使用
array\u fill\u keys()
代替
array\u flip()
,这样我就可以设置一个空值,允许过滤器工作。

首先,如果输入数组是MySQL查询的结果集,那么应该通过ORDER BY子句对数据进行排序
FIELD()
是一个很好的工作工具,有点奇怪,你需要反转排序逻辑并在函数后写入
DESC

资源:(向下滚动至“gotcha”)

SQL Fiddle演示:


除此之外,我将提供奈杰尔和埃迪解决方案的两个精炼版本,利用php7+的优点。您选择实施哪一项与以下内容有关:

  • 是否允许具有重复
    id
    值的元素在进程中“生存”
  • 对于实际项目数据(输入数组和自定义订单数组的大小),哪一种执行效率更高
  • 个人偏好(两个代码段都可以合理地写成3到5行,因此简洁性不是一个标准)
  • 解决方案#1:和

    *注意:这不会生成过大的
    null
    值数组,也不会删除“false”值


    *我将再次声明,如果输入数组中存在重复的
    id
    值,则使用
    array\u column()
    将损坏数据。

    try
    usort()
    。据我所知,usort正在比较数组中的两个值,而不是与外部值映射进行比较……或者至少我找不到一个值。你能发布你到目前为止所做的吗?到目前为止,我已经迭代了对象数组,并将每个对象与列表进行了比较。如果发现,我将插入一个新数组并从$inputArray中取消设置值,但我认为这是次优的,必须是一种更好的方法..可能的重复我认为这是一种更优雅的方法。工作起来很有魅力*我认为它是首选方法的原因是,它过滤原始输入数组中的重复项,如果键不存在,则不会失败。我不希望
    0
    将是
    id
    的有效值,但如果将来有人使用此方法,
    array\u filter()
    将使用
    null
    值销毁它们。谢谢,关于SQL,它不是很不幸……关于array\u search的重构版本,第一个响应更短、更高效……否?效率很大程度上取决于所涉及阵列的大小。如果你是指重复页面上的
    usort()
    -
    array\u search()
    答案,我没有对它们进行测试,但是,
    array\u search()
    isset()更难工作。使用
    isset()
    的代价是只需调用
    array\u flip()
    即可设置它
    array\u search()
    实际遍历数组,并在找到匹配项时将其打断
    isset()
    不能做到这一点——这就是php处理哈希映射的神奇之处。我没有资格详细解释这一点。
    Array
    (
        [0] => stdClass Object
            (
                [id] => 5
            )
    
        [1] => stdClass Object
            (
                [id] => 8
            )
    
        [2] => stdClass Object
            (
                [id] => 7
            )
    
    )
    
    $input = array_column($inputArray, null, "id");   
    $sort = array_fill_keys($sortingArray, null);
    $output = array_filter(array_replace($sort, $input));
    
    $array = [
        (object)['id' => 8],
        (object)['id' => 7],
        (object)['id' => 5]
    ];
    
    $order = [5, 8, 1];  // custom sort order
    
    $order = array_flip($order);  // restructure for easy lookup with isset()
    $order[''] = max(array_column($array, 'id')) + 1;  // append value higher than max for outlying ids
    
    usort($array, function($a, $b) use ($order) {
        return ($order[$a->id] ?? $order['']) <=> ($order[$b->id] ?? $order['']);
    });
    var_export($array);
    
    $array = [
        (object)['id' => 8],
        (object)['id' => 7],
        (object)['id' => 5]
    ];
    
    $order = [5, 8, 1];
    
    $order = array_flip($order);                            // flip for future key comparisons
    $keyed = array_column($array, null, 'id');              // declare id values as new keys
    $filtered_order = array_intersect_key($order, $keyed);  // remove unwanted order keys
    $replaced = array_replace($filtered_order, $keyed);     // apply objects to output array
    var_export(array_values($replaced));                    // re-index the output (if desired)