反转foreach列表项的顺序

102

我希望倒序输出这段代码中的列表项。基本上,这是一组从最古老到最近的年份,我正在尝试反转该输出。

<?php
    $j=1;     
    foreach ( $skills_nav as $skill ) {
        $a = '<li><a href="#" data-filter=".'.$skill->slug.'">';
        $a .= $skill->name;                 
        $a .= '</a></li>';
        echo $a;
        echo "\n";
        $j++;
    }
?>  
9个回答

212

倒着走

如果你正在寻找一个纯粹的PHP解决方案,你也可以简单地通过倒数计数来访问列表,从前到后访问:

$accounts = Array(
  '@jonathansampson',
  '@f12devtools',
  '@ieanswers'
);

$index = count($accounts);

while($index) {
  echo sprintf("<li>%s</li>", $accounts[--$index]);
}

以上代码将$index设置为元素的总数,然后从后往前访问它们,减小索引值以进行下一次迭代。

反转数组

你还可以利用array_reverse函数来颠倒数组的值,从而可以按相反的顺序访问它们。
$accounts = Array(
  '@jonathansampson',
  '@f12devtools',
  '@ieanswers'
);

foreach ( array_reverse($accounts) as $account ) {
  echo sprintf("<li>%s</li>", $account);
}

2
@Slawek 如果数组已经排序,为什么反转一定比倒序遍历更好呢? - Sampson
5
因为如果在循环中使用数组之前先反转它,你以后可以轻松地更改它。当您将循环逻辑与数据绑定时,更改顺序将迫使您也更改循环。 - Slawek
1
@Slawek 我不确定我理解了。倒序遍历数组是一种常见的做法,而且在未来处理数组时不需要任何谨慎,因为它实际上并不修改数组。 - Sampson
1
@Slawek 我并不持有异议。虽然我没有看到用户遵循任何形式的MVC模式的迹象。当然,如果他们有一个控制器或模型,在许多情况下最好在那里对数组进行排序。 - Sampson
2
虽然性能不是很好,但代码可读性更强 :-) - eyal_katz
显示剩余4条评论

35

28

array_reverse() 不会改变源数组,而是返回一个新的数组。(参见 array_reverse()。)因此,您需要先存储新数组,或者在 for 循环的声明中使用该函数。

<?php 
    $input = array('a', 'b', 'c');
    foreach (array_reverse($input) as $value) {
        echo $value."\n";
    }
?>

输出结果将为:

c
b
a

因此,针对原帖作者的问题,代码变成:

<?php
    $j=1;     
    foreach ( array_reverse($skills_nav) as $skill ) {
        $a = '<li><a href="#" data-filter=".'.$skill->slug.'">';
        $a .= $skill->name;                 
        $a .= '</a></li>';
        echo $a;
        echo "\n";
        $j++;
}

最后,我猜测$j可能是在尝试获取$skills_nav反向遍历的计数器,或者是用于计算$skills_nav数组元素个数的变量。如果是前者,在找到正确解决方案后应将其删除。如果是后者,则可以在循环外部使用$j = count($skills_nav)替换。


8

如果你不介意破坏数组(或者它的临时副本),你可以这样做:

$stack = array("orange", "banana", "apple", "raspberry");

while ($fruit = array_pop($stack)){
    echo $fruit . "\n<br>"; 
}

生成:

raspberry 
apple 
banana 
orange 

我认为这个解决方案比操纵索引更清晰易懂,而且你不太可能引入索引操作错误,但它的问题在于:如果你需要先创建一个临时副本数组,那么你的代码很可能会花费更长的时间来运行。

操纵索引可能会运行得更快,并且如果你实际上需要引用索引,那么它也可能会派上用场,如下所示:

$stack = array("orange", "banana", "apple", "raspberry");
$index = count($stack) - 1;
while($index > -1){
    echo $stack[$index] ." is in position ". $index . "\n<br>";
    $index--;
} 

但是正如你所看到的,你必须非常小心地处理索引...


2
array_pop方法比array_reverse方法慢3倍:https://3v4l.org/3jaTT - Finesse

5

您可以使用usort函数创建自己的排序规则。


这样做性能不佳,因为数组已经有序(只需反转顺序)。 - mickmackusa

5
假设您只需要反转一个索引数组(不是关联数组或多维数组),一个简单的 for循环 就足够了:
$fruits = ['bananas', 'apples', 'pears'];
for($i = count($fruits)-1; $i >= 0; $i--) {
    echo $fruits[$i] . '<br>';
} 

2
如果您的数组是通过SQL查询填充的,请考虑在MySQL中反转结果,例如:
SELECT * FROM model_input order by creation_date desc

0

如果您的数组中没有布尔假值,您可以使用基于内部指针函数的下一段代码:

$array = ['banana', 'apple', 'pineapple', 'lemon'];

$value = end($array);
while ($value !== false) {
     // In case you need a key
    $key = key($array);

    // Do something you need to
    echo $key . ' => ' . $value . "\n";

    // Move pointer
    $value = prev($array);
}

这个解决方案适用于具有任意键的关联数组,并且不需要更改现有数组或创建新数组。


-2
<?php
    $j=1; 


      array_reverse($skills_nav);   


    foreach ( $skills_nav as $skill ) {
        $a = '<li><a href="#" data-filter=".'.$skill->slug.'">';
        $a .= $skill->name;                 
        $a .= '</a></li>';
        echo $a;
        echo "\n";
        $j++;
    }
?> 

2
array_reverse()不改变源数组,而是返回一个新数组。 - Cláudio Silva

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接