Обратный порядок элементов списка foreach

88

Я хотел бы изменить порядок элементов списка этого кода. По сути, это набор лет, идущих от самых старых к недавним, и я пытаюсь изменить этот результат.

<?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++;
    }
?>  
блкеди
источник

Ответы:

186

Ходьба назад

Если вы ищете чисто 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
1
Отлично, array_reverse сработал! Спасибо, Джонатан, и всем остальным.
blkedy
4
@JonathanSampson - потому что, если вы перевернете массив перед использованием его в цикле, вы можете просто изменить его в будущем. Когда вы связываете логику цикла с данными, изменение порядка заставит также изменить цикл.
Slawek
1
@Slawek Я не уверен, что понимаю. Обратный отсчет по массиву является обычной практикой и не требует осторожности при работе с массивом в будущем, поскольку фактически не изменяет массив.
Sampson
1
@Slawek Я не с этим не согласен. Думал, что я не вижу никаких указаний на то, что пользователь следует какому-либо шаблону MVC. Конечно, если у них есть контроллер или модель, во многих случаях может быть разумнее отсортировать массив там.
Sampson
21

array_reverse()не изменяет исходный массив, а возвращает новый массив. (См array_reverse().) Итак, вам нужно либо сначала сохранить новый массив, либо просто использовать функцию в объявлении цикла for.

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

Результат будет:

c
b
a

Итак, чтобы обратиться к OP, код выглядит следующим образом:

<?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).

ДжейсонГаблер
источник
7

Если вы не против уничтожить массив (или его временную копию), вы можете сделать:

$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--;
} 

Но, как видите, с индексом нужно быть очень осторожным ...

Дамиан Грин
источник
1
array_popПодход в 3 раз медленнее , чем array_reverseподход: 3v4l.org/3jaTT
Finesse
4

Предполагая, что вам просто нужно перевернуть индексированный массив (не ассоциативный или многомерный), достаточно простого цикла for :

$fruits = ['bananas', 'apples', 'pears'];
for($i = count($fruits)-1; $i >= 0; $i--) {
    echo $fruits[$i] . '<br>';
} 
Феликс Ева
источник
3

Вы можете использовать функцию usort для создания собственных правил сортировки

Slawek
источник
1

Если ваш массив заполняется с помощью SQL-запроса, подумайте об изменении результата в MySQL, то есть:

SELECT * FROM model_input order by creation_date desc
Хьюго Триал
источник
-1
<?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++;
    }
?> 
user5168728
источник
1
array_reverse () не изменяет исходный массив, а возвращает новый массив.
Cláudio Silva