【问题标题】:PHP: usort with closure syntax "use()" [duplicate]PHP:使用闭包语法“use()”的usort [重复]
【发布时间】:2020-04-08 01:21:04
【问题描述】:

编辑:我重写了我的帖子,以便更清晰并提供具有真实价值的独立案例(不再使用 Ajax)。

我有 2 个完全相同的数组,除了一个具有相同的值但已清理(html、特殊字符等)。

我想根据“arrayClean”评估排序,但要根据该评估对“arrayOriginal”进行排序(而不是 arrayClean)。

所以,这就是我所拥有的:

<?php

$arrayOriginal  = array(
    array('id' => '100','surface' => '<span>300</span>','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100 ch','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '<b>1000</b>','whatever' => 'fgsdfg')
);

$arrayClean = array(
    array('id' => '100','surface' => '300','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '1000','whatever' => 'fgsdfg')
);

usort($arrayOriginal, function($a, $b) use (&$arrayClean) {
    return $a['surface'] < $b['surface'];
});

echo '<pre>'; print_r($arrayOriginal); echo '</pre>';

?>

这是我得到的(这是错误的,因为 arrayClean 似乎没有考虑到排序):

Array
(
[0] => Array
    (
        [id] => 100
        [surface] => <span>300</span>
        [whatever] => qSDqsd
    )

[1] => Array
    (
        [id] => 40489
        [surface] => <b>1000</b>
        [pwhatever] => fgsdfg
    )

[2] => Array
    (
        [id] => 5465
        [surface] => 100 ch
        [whatever] => ghjkghjk
    )

)

但是如果我单独使用arrayClean,只是为了检查排序脚本是否正确:

usort($arrayClean, function($a, $b) {
    return $a['surface'] < $b['surface'];
});

echo '<pre>'; print_r($arrayClean); echo '</pre>';

那么结果就是我所期望的:

Array
(
[0] => Array
    (
        [id] => 40489
        [surface] => 1000
        [whatever] => fgsdfg
    )

[1] => Array
    (
        [id] => 100
        [surface] => 300
        [whatever] => qSDqsd
    )

[2] => Array
    (
        [id] => 5465
        [surface] => 100
        [whatever] => ghjkghjk
    )

)

因此,似乎评估 arrayClean 但对 arrayOriginal 进行相应的排序是行不通的。它只评估和排序arrayOriginal。 我使用“use()”错了吗?我应该使用其他东西吗?

谢谢。

【问题讨论】:

  • 因为当您使用use 闭包时,它会通过值传递它,因此通过引用传递它尝试在array 名称之前添加&amp; 就像这样use(&amp;$arrayClean)
  • 谢谢。我通过在 use() 闭包中的数组之前添加“&”来尝试您的提议,但我得到的结果与以前完全相同。
  • 实际上,我编辑了我的初始帖子:无论有没有你的提议,arrayOriginal 实际上都是排序的,但不像 arrayClean 那样(如果我单独排序的话)。它以通常的方式对 arrayOriginal 进行排序,而不考虑 arrayClean。

标签: php arrays sorting


【解决方案1】:

假设两个数组都按一个公因子排序(即id)。

uksort($arrayOriginal, function($a, $b) use ($arrayClean) {
    return $arrayClean[$a]['surface'] < $arrayClean[$b]['surface'];
});

再次强调,为了使其工作,两个数组必须包含相同顺序的元素。在您的情况下,两个数组的元素必须按以下顺序(按 id):100、5465、40489

但我宁愿做这样的事情:

usort($arrayOriginal, function($a, $b) {
    return yourSurfaceCleanMethod($arrayOriginal['surface']) < yourSurfaceCleanMethod($arrayOriginal['surface']);
});

当然,这一切都取决于您的需求,但如果您仅使用 $arrayClean 作为对原始数组进行排序的参考,并且您拥有方便的 yourSurfaceCleanMethod,那么我肯定会执行上述操作。

【讨论】:

  • 我测试了脚本。它在这个测试用例之外不起作用(我知道你不应该推断)。 uksort 对 arrayOrginal 进行排序,但数组索引仍然存在。在排序之前,我有 Array(Array[0](s=300),Array[1](s=100),Array[2](s=1000))。之后,我得到 Array(Array[2](s=1000),Array[0](s=300),Array[1](s=100))。但我需要对内容进行排序并重新分配数组索引,如下所示:Array(Array[0](s=1000),Array[1](s=300),Array[2](s=100))。否则,导出此数组 (AJAX) 只会重新排序索引,我最终会得到与最初相同的数组。
  • 我最终会认为这是一个有效的答案,因为您在技术上回答了测试用例的范围。但是我还没有接受您的回答,以便引起人们的注意以解决我的实际问题。非常感谢您迄今为止提供的所有帮助。
  • @BachirMessaouri in order to solve my actual problem - 那你有什么实际问题?回答你的问题:不,你不使用use wrong,这是你在回调中的逻辑没有做需要做的事情。你应该用别的东西吗?也许,在编程中没有“唯一的方法”,但是做你想做的事情是完全可以的。
  • @BachirMessaouri 哦,好吧,我在上面看到你的评论......而且我不太明白你想用这些 id 实现什么......原来的问题没有提到它与ids有什么关系,只是按surface排序。您可能想要更新您的问题,提供输入和预期输出。
  • 没关系 Nemoden。你非常有帮助,因为它让我有一个很好的开始了解正在发生的事情。我最终找到了解决方案,并相应地更新了我的帖子。但是只是为了让您知道,当我说我要更新 ID 时,我并没有说我要根据键“Id”进行排序。我的意思是我想按表面排序,但最终,如果表面排序为 1000、300 100,我希望 ARRAY 索引为 Array(Array[0](s=1000),Array[1](s=300),数组[2](s=100))。我不是对 ARRAY 索引进行排序,我是说索引 0 是 1000,索引 1 是 300,索引 2 是 100。
【解决方案2】:

如果你的arrayOriginal应该根据HTML标签的内容进行排序,我认为不需要arrayClean。

strip_tags() 可用于您的排序函数中。

usort($arrayOriginal, function($a, $b) {
    return strip_tags($b['surface']) <=> strip_tags($a['surface']);
});

注意:使用宇宙飞船运算符可以得到正确的比较结果1、0和-1。

【讨论】:

  • 不仅仅是 html 标签。我认为数组内容表明了这一点。不过谢谢。
【解决方案3】:

出于礼貌,我接受了 Nemoden 的回答,因为从技术上讲,它根据其范围(所提供的测试用例)回答了问题。但这是我发现最适合我的解决方案:

$arrayOriginal  = array(
    array('id' => '100','surface' => '<span>300</span>','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100 ch','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '<b>1000</b>','whatever' => 'fgsdfg')
);

$arrayClean = array(
    array('id' => '100','surface' => '300','whatever' => 'qSDqsd'),
    array('id' => '5465','surface' => '100','whatever' => 'ghjkghjk'),
    array('id' => '40489','surface' => '1000','whatever' => 'fgsdfg')
);

$surface = array_column($arrayClean, 'Surface');

array_multisort($surface, SORT_DESC, SORT_REGULAR, $arrayOriginal);

然后我得到这个输出,这正是我想要的:

Array
(
    [0] => Array
        (
            [id] => 40489
            [surface] => <b>1000</b>
            [whatever] => fgsdfg
        )

    [1] => Array
        (
            [id] => 100
            [surface] => <span>300</span>
            [whatever] => qSDqsd
        )

    [2] => Array
        (
            [id] => 5465
            [surface] => 100 ch
            [whatever] => ghjkghjk
        )

)

Nemoden 的回答非常有帮助,但无论出于何种原因,它都给了我这个:

Array
(
    [1] => Array
        (
            [id] => 40489
            [surface] => <b>1000</b>
            [whatever] => fgsdfg
        )

    [0] => Array
        (
            [id] => 100
            [surface] => <span>300</span>
            [whatever] => qSDqsd
        )

    [2] => Array
        (
            [id] => 5465
            [surface] => 100 ch
            [whatever] => ghjkghjk
        )

)   

子数组以正确的顺序打印,但子数组索引没有改变。因此,当导出到 javascript“arrayOriginal”时,它会恢复到初始排序,因为子数组将再次根据它们的索引重新排序。至少,这是我所经历的。

无论如何,现在问题已经解决了,我在这里得到的答案非常有帮助。

谢谢。

【讨论】:

    猜你喜欢
    • 2018-08-02
    • 2011-08-23
    • 2018-02-15
    • 2013-01-06
    • 1970-01-01
    • 2020-05-23
    • 2015-12-07
    • 1970-01-01
    • 2018-02-19
    相关资源
    最近更新 更多