ChatGPT解决这个技术问题 Extra ChatGPT

如何按值对多维数组进行排序

如何按“order”键的值对该数组进行排序?

尽管这些值当前是连续的,但它们并不总是如此。

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

    [2] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
)
最快的方法是使用同构 sort-array 模块,它可以在浏览器和节点中本地工作,支持任何类型的输入、计算字段和自定义排序顺序。

P
Peter Mortensen

试试 usort。如果您仍在使用 PHP 5.2 或更早版本,则必须先定义一个排序函数:

function sortByOrder($a, $b) {
    return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

从 PHP 5.3 开始,您可以使用匿名函数:

usort($myArray, function($a, $b) {
    return $a['order'] - $b['order'];
});

最后,在 PHP 7 中,您可以使用 spaceship operator

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

要将其扩展到多维排序,如果第一个排序元素为零,请参考第二个/第三个排序元素 - 最好在下面解释。您也可以使用它对子元素进行排序。

usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});

如果您需要保留键关联,请使用 uasort() - 请参阅手册中的 comparison of array sorting functions


如果您需要回退/决胜局排序而不需要任何函数调用来准备值,则在单个宇宙飞船运算符的两侧声明一组规则。 1 2 如果后续排序规则包含功能开销,则在后续太空飞船运算符比较之间使用 ?:(三元运算符)。 3 这样就不会不必要地调用额外的函数。
P
Peter Mortensen
function aasort (&$array, $key) {
    $sorter = array();
    $ret = array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii] = $va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii] = $array[$ii];
    }
    $array = $ret;
}

aasort($your_array, "order");

这个答案缺少它的教育解释。
一个循环,然后是原生排序,然后是另一个循环?当然不是页面上最优雅或性能最好的片段。
一个解释将是有序的。
T
Tom Haigh

我使用这个功能:

function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key => $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}

array_sort_by_column($array, 'order');

编辑这个答案至少有十年的历史了,现在可能有更好的解决方案,但我根据一些评论的要求添加了一些额外的信息。

它之所以有效,是因为 array_multisort() 可以对多个数组进行排序。示例输入:

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

第一个 $sort_col 是一个二维数组,其值是我们想要排序的值,键与输入数组匹配。例如对于这个输入,选择键 $sort_col "order" 我们得到:

Array
(
    [0] => 3,
    [1] => 2
)

array_multisort() 然后对该数组进行排序(产生键顺序 1, 0),但这只是二维数组。因此,原始输入数组也作为 $rest 参数传递。当键匹配时,它将被排序,因此它的键也是相同的顺序,给出所需的结果。

笔记:

它通过引用传递,以便提供的数组被修改到位。

array_multisort() 可以像这样对多个附加数组进行排序,而不仅仅是一个


一个解释将是有序的。例如,想法/要点是什么?与其他解决方案相比有哪些权衡?性能特征是什么,理论和实际示例性能测量?例如,这个解决方案是否慢?
P
Peter VARGA

为此,我们可以使用“对多维或多维数组进行排序”的“array_multisort”方法。它的方法参数是

$keys - 一个被排序的数组

SORT_ASC - 排序顺序(升序)

排序标志(通常比较项目(不要更改类型)或数字或字符串)

$new - 然后是其余的数组。仅比较与先前数组中的等效元素相对应的元素。

'sort flags' 默认是 SORT_REGULAR 并且被省略。

$new = [
    [
        'hashtag' => 'a7e87329b5eab8578f4f1098a152d6f4',
        'title' => 'Flower',
        'order' => 3,
    ],
    [
        'hashtag' => 'b24ce0cd392a5b0b8dedc66c25213594',
        'title' => 'Free',
        'order' => 2,
    ],
    [
        'hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
        'title' => 'Ready',
        'order' => 1,
    ],
];
$keys = array_column($new, 'order');
array_multisort($keys, SORT_ASC, $new);
var_dump($new);

结果:

Array
(
    [0] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )
    [2] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )
)

虽然我喜欢了解宇宙飞船运算符,但这似乎是最容易理解和最直接的答案,其中包含 SORT_DESC 等有用选项和 sort_flags (php.net/manual/en/function.array-multisort.php) 的多个选项。
P
Peter Mortensen

我通常使用usort,并传递我自己的比较函数。在这种情况下,它非常简单:

function compareOrder($a, $b)
{
  return $a['order'] - $b['order'];
}
usort($array, 'compareOrder');

在 PHP 7 中使用 spaceship 运算符:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

它的工作原理谢谢 DESC 怎么样?
@Meas 用于 DESC 排序,您反转 ab 相对于 <=> 的位置。请参阅this answer
P
Peter Mortensen

要按“title”键的值对数组进行排序,请使用:

uasort($myArray, function($a, $b) {
    return strcmp($a['title'], $b['title']);
});

strcmp 比较字符串。

uasort() 按照定义的方式维护数组键。


这个答案忽略了 OP 的要求。该问题询问如何对 order 列进行排序。无论如何,宇宙飞船操作员(在接受的答案中演示)执行相同的比较而不进行迭代函数调用。
S
Shahbaz A.

使用 array_multisort()array_map()

array_multisort(array_map(function($element) {
      return $element['order'];
  }, $array), SORT_ASC, $array);

print_r($array);

DEMO


请注意,这种方法会发出通知。 array_multisort 引用它的第一个参数。
@Kami 在现成的演示链接中没有证据表明您的主张。我不会使用这个答案,因为 array_column() 更合适/更简洁。
这是 ajuchacko91 较早发布的答案的不太完善的版本。
U
Udo Held
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

这会处理大写和小写字母。


这如何回答按特定数组键排序的问题?
@Nitro此答案缺少其教育解释。这个答案似乎是另一个问题的正确答案。
P
Peter Mortensen

最灵活的方法是使用这种方法:

Arr::sortByKeys(array $array, $keys, bool $assoc = true): array

原因如下:

您可以按任何键排序(也可以嵌套,如 'key1.key2.key3' 或 ['k1', 'k2', 'k3'])

它适用于关联数组和非关联数组($assoc 标志)

它不使用引用 - 它返回一个新的排序数组

在你的情况下,它会很简单:

$sortedArray = Arr::sortByKeys($array, 'order');

此方法是 this library 的一部分。


m
mickmackusa

PHP 7.4 及更高版本的工作“箭头函数”语法:

uasort($yourArray, fn($a, $b) => $a['order'] <=> $b['order']);

漂亮的印刷品

echo '<pre>';
print_r($yourArray);

颠倒顺序有多难?可以更改 fn 还是需要 array_reverse
微小的细节被称为spaceship operator
uasort($yourArray, fn($a, $b) => -1*($a['order'] <=> $b['order'])); 反向...
G
Guillermo Phillips

正如接受的答案所述,您可以使用:

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

如果您需要按多列排序,那么您将执行以下操作:

usort($myArray, function($a, $b) {
    return [$a['column1'],$a['column2']] <=> [$b['column1'],$b['column2']];
});

这可以扩展到数据中的任意数量的列。这取决于您可以在 PHP 中直接比较数组这一事实。在上面的示例中,数组将首先按 column1 排序,然后按 column2。但是您可以按任何顺序按列排序,例如:

usort($myArray, function($a, $b) {
    return [$a['column2'],$a['column1']] <=> [$b['column2'],$b['column1']];
});

如果您需要对一列升序和另一列降序进行排序,则将降序列交换到运算符 <=> 的另一侧:

usort($myArray, function($a, $b) {
    return [$a['column1'],$b['column2']] <=> [$b['column1'],$a['column2']];
});

一个较早的 demonstration of multi-column sorting,在过去 14 年的内容生成中,Stack Overflow 上会有很多。和another
this one。嗯,我重新阅读问题和这个答案的次数越多,似乎这个答案应该已经发布在不同的页面上,因为它复制了已接受答案中的建议,然后扩展了问题范围。最好找到一个尚未演示如何对多列进行排序的页面。
我想我会不知道我的答案属于哪里。你是对的,我回答的比问的问题多。人们会发现这个问题或其他问题,因此他们更有可能遇到我们的答案和这种(简单的)排序方式。我们只需要点赞!
P
Peter Mortensen

如果有人需要根据键排序,最好使用以下内容:

usort($array, build_sorter('order'));

function build_sorter($key) {
   return function ($a, $b) use ($key) {
      return strnatcmp($a[$key], $b[$key]);
   };
}

基于 php.net/manual/en/function.usort.php 中的示例 4
P
Peter Mortensen

此解决方案适用于 usort(),具有易于记忆的多维排序符号。使用了宇宙飞船运算符 <=>,它可从 PHP 7 获得。

usort($in,function($a,$b){
  return $a['first']   <=> $b['first']  //first asc
      ?: $a['second']  <=> $b['second'] //second asc
      ?: $b['third']   <=> $a['third']  //third desc (a b swapped!)
      //etc
  ;
});

例子:

$in = [
  ['firstname' => 'Anton', 'surname' => 'Gruber', 'birthdate' => '03.08.1967', 'rank' => 3],
  ['firstname' => 'Anna', 'surname' => 'Egger', 'birthdate' => '04.01.1960', 'rank' => 1],
  ['firstname' => 'Paul', 'surname' => 'Mueller', 'birthdate' => '15.10.1971', 'rank' => 2],
  ['firstname' => 'Marie', 'surname' => 'Schmidt ', 'birthdate' => '24.12.1963', 'rank' => 2],
  ['firstname' => 'Emma', 'surname' => 'Mueller', 'birthdate' => '23.11.1969', 'rank' => 2],
];

第一项任务:按等级升序,姓氏升序排序

usort($in,function($a,$b){
  return $a['rank']      <=> $b['rank']     //first asc
      ?: $a['surname']   <=> $b['surname']  //second asc
  ;
});

第二个任务:按等级 desc、姓氏 asc、firstmame asc 排序

usort($in,function($a,$b){
  return $b['rank']      <=> $a['rank']       //first desc
      ?: $a['surname']   <=> $b['surname']    //second asc
      ?: $a['firstname'] <=> $b['firstname']  //third asc
  ;
});

第三项任务:按等级降序排列,生日升序排列

日期不能用这种表示法排序。它是用 strtotime 转换的。

usort($in,function($a,$b){
  return $b['rank']      <=> $a['rank']       //first desc
      ?: strtotime($a['birthdate']) <=> strtotime($b['birthdate'])    //second asc
  ;
});

这个问题只在一列上排序。您的回答更适合此页面:stackoverflow.com/q/3232965/2943403stackoverflow.com/q/7127764/2943403
P
Peter Mortensen

您可以使用 usort 和带有回调函数的用户定义排序函数:

usort($new, fn($a, $b) => $a['order'] - $b['order']);

TRICK:您可以使用 a > ba - ba <=> b升序顺序进行排序。对于 降序 订单,只需 ab 的交换位置。


所有这些选项都会产生稳定的排序吗?
D
DanimalReks

我发现这很有帮助:

    $columns = array_column($data, "order");
    array_multisort($columns, SORT_ASC, $data);

Sort by name ascending


P
Peter Mortensen

让我们面对现实吧:PHP 没有一个简单的开箱即用的函数来正确处理每个数组排序场景。

这个例程很直观,这意味着更快的调试和维护:

// Automatic population of the array
$tempArray = array();
$annotations = array();
// ... some code
// SQL $sql retrieves result array $result
// $row[0] is the ID, but is populated out of order (comes from
// multiple selects populating various dimensions for the same DATE
// for example
while($row = mysql_fetch_array($result)) {
    $needle = $row[0];
    arrayIndexes($needle);  // Create a parallel array with IDs only
    $annotations[$needle]['someDimension'] = $row[1]; // Whatever
}
asort($tempArray);
foreach ($tempArray as $arrayKey) {
    $dataInOrder = $annotations[$arrayKey]['someDimension'];
    // .... more code
}

function arrayIndexes ($needle) {
    global $tempArray;
    if (!in_array($needle, $tempArray)) {
        array_push($tempArray, $needle);
    }
}

“让我们面对现实吧:php 没有一个简单的开箱即用的函数来正确处理每个数组排序场景。”这正是 usort/ksort/asort 为 ^^' 设计的
实际上 PHP a lot of sorting functions 可以用来处理每个数组排序场景。
关于调试和维护,使用 global 是一个巨大的危险信号,是 generally discouraged。为什么为这个问题演示 mysql_fetch_array 而不是 OP 的源数组,并且没有解释您的代码在做什么以及可以预期结果是什么?总体而言,这是一种非常复杂的方法来实现预期的最终结果。
@tonygil 我无法从您的答案和 OP 的数据集中确定您的预期结果。这对您来说可能很明显,但我不知道您的回答如何回答 OP 的问题。但是,您可以使用 pass by-reference 而不是使用 global 请参阅: 3v4l.org/FEeFC 这会生成一个明确定义的变量,而不是一个可以全局更改和访问的变量。
这个答案与原来的问题相差太大。如果这个片段与问题的样本数据不相似,研究人员如何将此解决方案与其他答案进行比较并得出最喜欢的答案?