Чіткий спосіб пропустити перший елемент в індексі на основі циклу


9

У мене є цикл for, де я повинен пропустити перший елемент у нульовому масиві.

Який із них чіткіше показує мої наміри?

for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

або

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}

28
Ні, $i=2-1це вищий спосіб. : /
yannis

7
Можливо, я б пішов на перший варіант і додав коментар, щоб пояснити, чому перший елемент потрібно пропустити.
Вінсент Савард

3
Чіткість - це те, на що я прагну, я редагував питання. Це ясніше?
Томаш Зубірі

10
Не використовувати PHP - це найкращий спосіб.
кіт

3
Чи має PHP конструкцію foreach? Ви могли б зробити foreach ($i in range(1, count))(як би це не виглядало в PHP). Або щось на зразок того, foreach ($item in array.skip(1))що зробила б людина C #.
usr

Відповіді:


23

Я ненавиджу обох.

Хто сказав, що ви можете використовувати магічні числа? Якщо ви збираєтеся розпочати з зміщенням 1, як щодо того, щоб сказати нам, ЧОМУ ви починаєте зі зміщенням 1. Додавання однаково магічного нуля мені нічого не пояснює.

Це компенсація корисного навантаження? Це якась паскальна рядок, яку ви перетворюєте на нульову завершену рядок c? Скажіть, будь ласка, що відбувається.

Вибачте, але я витратив більшу частину своєї кар'єри на розшифровку безглуздих таємниць, як ця, і моє терпіння до них знесилилося. Чи справді багато чого запитати змінну з гідним ім'ям ?

Під гідним іменем я маю на увазі ім’я, яке пояснює ЧОМУ ми пропускаємо перший елемент. Не те, що просто говорить, що ми пропускаємо перший елемент. 1 сказав мені, що самостійно.


20
0 і 1 - не магічні числа.
user949300

19
@ user949300 О, вони, звичайно, є тут. Це просто цифри, які час від часу не є магічними. Тільки тому, що 2 завжди є магічним числом, не означає, що 1 ніколи не є магічним числом. Магія походить від пропущеного значення. Що тут значить чорт, починаючи з 1 зміщення? Яку користь додає тут 0? О так, ці цифри, безумовно, тут магічні. Я бачу, як з них стікає пиловий піксі.
candied_orange

4
Звичайно, я почну визначатись static final int LONELIEST_NUMBER = 1у всьому своєму Java-коді. :-) Ось так, при подальшій думці я хочу скасувати свою відповідь, але не можу, якщо ви її не відредагуєте. Дурне ТАК правило?
user949300

6
@Eiko: Якщо немає пояснень, чому цикл починається на другому елементі, практично гарантується, що якийсь програміст технічного обслуговування змінить цикл, щоб розпочати його на першому елементі. Ось чому цифра 1 є магічним числом у цьому контексті.
Барт ван Іґен Шенау

2
@BartvanIngenSchenau Я припускав, що в контексті буде негайно помітна причина. Як і порівняння елементів з попередниками (що я вважав найчастішим випадком використання, починаючи з 1 - і я не бачу тут жодної корисної постійної назви). Якщо перший елемент має деяке ультраспеціальне значення, дизайн може бути порушений, і там повинні бути кращі виправлення, ніж називати цей індекс. Я не кажу, що тут ніколи немає причини вводити змінну. Просто я вважаю, що такі випадки (або, можливо, лише мають бути) дуже рідкісні.
Ейко

12

Коротка відповідь: перший варіант краще.

Другий варіант просто додає шуму. Це дуже малоймовірно, що 0 + 1 допомагає читачеві зрозуміти, що це могло бути 0, але це 1. Набагато більше шансів, що він буде спантеличений короткий момент і відвернеться від того, про що йде петля. Особливо мовою, де всі масиви починаються з 0.

Як вже згадувалося, якщо ви хочете наголосити на тому, що цикл починається з 1, а не від 0, просто додайте коментар.


10

Не кажіть нам, що ви пропускаєте перший пункт - ми можемо це бачити. Що не очевидно, це чому . Тож .. якщо це не очевидно з контексту, скажіть нам, чому:

// array[0] is just a header
for($i=1 ; $i < count(array) ; $i++){
    array[$i];
}

Або, якщо ви проти коментарів, щось на кшталт:

$lastHeaderIndex = 0;
for($i = $lastHeaderIndex + 1 ; $i < count(array) ; $i++){
    array[$i];
}

Не використовуйте коментарі та хитрість, щоб нагадати нам, як працює мова.


6

Ваш приклад виглядає надуманим. У реальному коді світу факт, що петлі потрібно починати з другого елемента масиву, найвірогідніше, очевидний із наступних рядків коду. Наприклад, якщо справжній код виглядає так

for($i=1 ; $i < count(array) ; $i++){
    array[$i-1]=array[$i];
}

не було б пояснень чи конструкції "0 + 1", необхідних для того, щоб зрозуміти, чому цикл починається з 1, а не з 0.

Однак якщо код всередині циклу не пояснює причини настільки очевидним чином (можливо, він array[0]має особливе значення і повинен розглядатися інакше, ніж решта елементів), тоді додайте пояснюючий коментар. Але перш ніж зробити це, подумайте двічі, чи зможете ви уникнути array[0]такого особливого значення, і реорганізуйте навколишній код, який, мабуть, буде кращою альтернативою.


У таких ситуаціях, як ваш код прикладу, я хотів би називати змінні "oneBasedIndex" або "zeroBasedIndex". Хоча щось ще більш конкретне для цього завдання було б краще.
user949300

5

Ніколи не бачив варіант №2, але мені це подобається. Чому? З варіантом №1 мені цікаво, чи забув програміст, що масиви починаються з 0. Варіант №2 дає зрозуміти, що вони навмисно починаються з 1.

Однак, найкраще в будь-якому випадку додати коментар, чому ви пропускаєте елемент.

Або, якщо ви можете легко описати, чому ви починаєте з одного, використовуйте константу. Наприклад, якщо дивитися на аргументи командного рядка, щось подібне

define ('FIRST_REAL_ARGUMENT', 1);
for ($i=FIRST_REAL_ARGUMENT; ...)

Особисто я, напевно, просто використав би коментар замість цього, YMMV.


Я скажу, що за межами середовищ, де ти маєш справу з початківцями, у мене ніколи не було проблем, щоб колеги забували, що масиви починаються з нуля. Я міг бачити це, якби у вашій роботі також використовувалася така мова, як MATLAB, але в більшості середовищ я вважаю, що програміст знав, що вони роблять. І чорт забирати цикл у 1 - це досить чорт звичайно. Існує досить багато причин пропустити перший елемент чогось.
Кет

@Kat Ця причина повинна бути зрозумілою для майбутніх читачів. Я вважаю за краще, що майбутній програміст не знає, що це робить.
A1rPun

2

Сумніваюсь, когось би хтось збентежив. Ми всі повинні були це зробити. Настільки, що другий набагато частіше плутає. "Чому там 0+? Чи якимось чином вони перекрили + оператора?"

Пристойний компілятор перетворить другий на перший у будь-якому випадку, але схоже, що ви використовуєте PHP, що інтерпретується. Тож кожен раз, коли перекладач потрапляє в цю петлю, потрібно буде насправді додати 0 і 1. Не велика справа, але навіщо змушувати перекладача виконувати роботу?


2

Використовуйте змінну, яка пояснює початкову точку.

Потрібно " пропустити перший елемент у нульовому масиві ", наприклад:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}

6
Мені подобається використовувати змінну, але я ненавиджу це ім'я. Це не пояснює, Чому ви пропускаєте перший елемент. А 1 мені це все одно говорить. Яка користь є змінною, яку потрібно перейменувати, коли її значення змінюється? Я знаю, що ОП не дала нам поняття, чому для того, щоб вибрати хороше ім’я, вам доведеться скласти причину. Без кращого імені я вважаю за краще мати 1 спинку.
candied_orange

@CandiedOrange Я погоджуюся з вами, що назва змінної має бути більш значущим, але проблема, яку вона представляє, не пояснює, чому він хоче пропустити перше значення. Моя думка, я просто навожу приклад, автор може вибрати ім’я, яке найкраще підходить йому.
катта

Будь ласка, не вчите так. Це досить заплутано. Для багатьох кодерів буде досягнуто найпростішого імені, яке вони можуть, щоб вони могли повернутися до написання важкого для розуміння коду. Серйозно, я вважаю за краще мати справу з 1, ніж з цим.
candied_orange

1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Якщо ви нав'язливі до всіх циклів, починаючи з нуля, ви можете використовувати оператор продовження. Додайте коментар до того, чому ви пропускаєтесь, оскільки зазвичай це не сталося.


2
Проблема з цим варіантом означає, що ми будемо оцінювати це для кожного окремого елемента, додаючи n додаткових порівнянь до циклу, при цьому просто пропускаючи перший через якийсь інший метод (зміщення масиву, починаючи з i = 1, що б не було ) означає лише виконувати необхідну роботу.
Кевінський збір

3
@KevinFee Якщо ви не маєте справу з масивними масивами, я б сказав, що це нескладне порівняння не буде проблемою. І мені дуже подобається чіткість if first then skipіз коментарем, що говорить чому. Досі без контексту жодне з рішень не є "найкращим"
Іван Пінтар

-2

Що б я зробив, це видалити перший елемент перед циклом. Створіть новий масив, якщо вам потрібно. Поясніть в коментарі, чому ви це робите. А потім просто зробіть просте передбачення.

$arrayCopy = $array; // in case you don't want to touch the original array
array_shift($arrayCopy); // removing first element because of X reason.
foreach($arrayCopy => $element) { 
    // do stuff
}

Таким чином ваш намір ідеально зрозумілий.

Щоб уточнити далі, ви можете зафіксувати код методом з відповідною назвою, щоб зробити речі зрозумілішими.

function doStuffToAllButTheFirst($array) { // this copies the original array, so there are no sideffects
    array_shift($array);
    foreach($array => $element) { // do stuff }  
}

Однак у всьому цьому поки що відсутній контекст. Що ви хочете зробити з елементами? Ви повернете новий масив? Чи дбаєте ви про оригінал та новий масив після вас doStuff()?

У будь-якому випадку, тут немає чіткої відповіді, і рішення, як зробити код читабельним, дуже залежить від контексту.


1
Мені це подобається, бо зараз мені не потрібно мати справу з індексами, що завжди є плюсом.
Томаш Зубірі

1
Недоліком тут є те, що якщо ви не хочете побічних ефектів, вам потрібно скопіювати весь масив.
Томаш Зубірі

1
А що, якщо причина, яку ми починаємо з 1, полягає в тому, що ми робимо $array[$i-1] = $array[$i]щось подібне, відповідно до відповіді @ DocBrown?
Кевінський збір

1
Це мені здається жахливим. Окрім усієї неефективності, побічних ефектів та неможливості вирішити досить поширені випадки використання 1(див. Коментар Кевіна Лі), це зовсім не робить код зрозумілішим. Читач повинен зрозуміти array_shift, що він робить, як це працює. Можливо, цей рядок коду є помилкою? Чи модифікує масив чи повертає новий? Він вставляє елемент чи видаляє його? Змінює він показники чи ні? Я не бачу, як використання одноосновного циклу не було б величезним вдосконаленням цієї функції (з огляду на її ім'я, миттєво зрозуміле).
Ейко

1
Відповіді на ці питання сильно залежать від контексту. А що стосується ефективності, я б взяв на себе передбачуваність на будь-який день ... Будь-яка різниця в роботі в більшості випадків майже невидима.
Іван Пінтар
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.