Prosty sposób na pominięcie pierwszego elementu w indeksie opartym na pętli

9

Mam pętlę for, w której muszę pominąć pierwszy element w tablicy zerowej.

Który z nich pokazuje moje zamiary jaśniej?

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

lub

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}
Tomas Zubiri
źródło
28
Ani też nie $i=2-1jest lepszy sposób. : /
yannis,
7
Prawdopodobnie wybrałbym pierwszą opcję i dodałbym komentarz wyjaśniający, dlaczego pierwszy element musi zostać pominięty.
Vincent Savard,
3
Celem jest przejrzystość, zredagowałem pytanie. Czy to jest jaśniejsze?
Tomas Zubiri,
10
Nie używanie PHP jest najlepszym sposobem.
kot
3
Czy PHP ma konstrukcję foreach? Możesz zrobić foreach ($i in range(1, count))(cokolwiek to wygląda w PHP). Lub coś takiego, foreach ($item in array.skip(1))co zrobiłby osoba C #.
usr

Odpowiedzi:

23

Nienawidzę obu.

Kto powiedział, że możesz użyć magicznych liczb? Jeśli zamierzasz zacząć od przesunięcia 1, powiedz nam, dlaczego zaczynasz od przesunięcia 1. Dodanie równie magicznego zera nic mi nie wyjaśnia.

Czy to jest przesunięcie ładunku? Czy to jakiś ciąg pascal, który konwertujesz na zakończony zerem łańcuch c? Powiedz nam, co się dzieje.

Przepraszam, ale zmarnowałem wiele z mojej kariery, dekodując takie bezsensowne tajemnice, a moja cierpliwość do nich osłabła. Czy zmienna o przyzwoitej nazwie jest naprawdę zbyt wymagająca?

Przez dobre imię rozumiem imię, które wyjaśnia, DLACZEGO pomijamy pierwszy element. Nie jest to coś, co po prostu mówi, że pomijamy pierwszy element. 1 powiedział mi to samo.

candied_orange
źródło
20
0 i 1 nie są magicznymi liczbami.
user949300,
19
@ user949300 Och, na pewno tu są. Są to po prostu liczby, które czasami nie są magiczne. To, że 2 jest zawsze liczbą magiczną, nie oznacza, że ​​1 nigdy nie jest liczbą magiczną. Magia pochodzi z brakującego znaczenia. Co do cholery znaczy tutaj od 1 offsetu? Do czego służy dodanie 0? O tak, te liczby są tutaj z pewnością magiczne. Widzę kapiącą z nich wróżkę.
candied_orange
4
Jasne, zacznę definiować static final int LONELIEST_NUMBER = 1w całym moim kodzie Java. :-) To powiedziawszy, dalej myślę, że chciałbym nie głosować na twoją odpowiedź, ale nie może, chyba że ją edytujesz. Głupia zasada SO?
user949300,
6
@Eiko: Jeśli nie ma wyjaśnienia, dlaczego pętla zaczyna się od drugiego elementu, jest praktycznie zagwarantowane, że jakiś programista konserwacji zmieni pętlę, aby rozpocząć od pierwszego elementu. Dlatego w tym kontekście cyfra 1 jest liczbą magiczną.
Bart van Ingen Schenau
2
@BartvanIngenSchenau Zakładałem, że w tym kontekście będzie natychmiast widoczny powód. Jak porównanie elementów z ich poprzednikami (które uważałem za najczęstszy przypadek użycia, zaczynając od 1 - i nie widzę tutaj żadnej użytecznej stałej nazwy). Jeśli pierwszy element ma jakieś wyjątkowe znaczenie, projekt może być zepsuty i powinny istnieć lepsze poprawki niż nazywanie tego indeksu. Nie twierdzę, że nigdy nie ma powodu, aby wprowadzać tutaj zmienną. Po prostu myślę, że te przypadki są (a może powinny być) bardzo rzadkie.
Eiko,
12

Krótka odpowiedź: pierwsza opcja jest lepsza.

Druga opcja po prostu dodaje hałas. Jest bardzo mało prawdopodobne, że 0 + 1 pomaga czytelnikowi zrozumieć, że mogło to być 0, ale jest to 1. O wiele bardziej prawdopodobne, że zostanie zaintrygowany na chwilę i odciągnie uwagę od tego, o co chodzi w pętli. Zwłaszcza w języku, w którym wszystkie tablice zaczynają się od 0.

Jak już wspomniano, jeśli chcesz podkreślić fakt, że pętla zaczyna się od 1, a nie 0, po prostu dodaj komentarz.

Florian F.
źródło
10

Nie mów nam, że pomijasz pierwszy przedmiot - możemy to zobaczyć. Nie jest oczywiste, dlaczego . Więc .. jeśli nie jest to oczywiste z kontekstu, powiedz nam dlaczego:

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

Lub, jeśli masz awersję do komentarzy, coś takiego:

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

Nie używaj komentarzy i podstępów, aby przypominać nam, jak działa ten język.

svidgen
źródło
6

Twój przykład wygląda na wymyślony. W prawdziwym kodzie fakt, że pętle muszą zaczynać się od drugiego elementu tablicy, najprawdopodobniej wynika z następujących linii kodu. Na przykład, jeśli prawdziwy kod wygląda tak

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

nie byłoby żadnego wyjaśnienia ani konstrukcji „0 + 1”, aby wyjaśnić, dlaczego pętla zaczyna się od 1 zamiast 0.

Jeśli jednak kod wewnątrz pętli nie wyjaśnia przyczyn w tak oczywisty sposób (być może array[0]ma specjalne znaczenie i musi być traktowany inaczej niż pozostałe elementy), dodaj komentarz wyjaśniający. Ale zanim to zrobisz, zastanów się dwa razy, czy możesz uniknąć array[0]tego specjalnego znaczenia, i zreorganizuj otaczający kod, co prawdopodobnie byłaby lepszą alternatywą.

Doktor Brown
źródło
W sytuacjach takich jak twój przykładowy kod lubię nazywać zmienne „oneBasedIndex” lub „zeroBasedIndex”. Choć coś jeszcze bardziej specyficznego dla tego zadania byłoby lepsze.
user949300,
5

Nigdy nie widziałem opcji # 2, ale podoba mi się. Dlaczego? Z opcją nr 1 zastanawiałbym się, czy programista zapomniał, że tablice zaczynają się od 0. Opcja nr 2 wyjaśnia, że ​​celowo zaczynają od 1.

To powiedziawszy, najlepiej w obu przypadkach dodać komentarz, dlaczego pomijasz element.

Lub, jeśli możesz łatwo opisać, dlaczego zaczynasz od jednego, użyj stałej. Na przykład, patrząc na argumenty wiersza poleceń, coś podobnego

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

Osobiście prawdopodobnie po prostu użyłbym komentarza YMMV.

użytkownik949300
źródło
Powiem, że poza środowiskami, w których masz do czynienia z początkującymi, nigdy nie miałem problemu, aby współpracownicy zapominali, że tablice zaczynają się od zera. Widziałbym, jak to się dzieje, jeśli twoja praca używa również języka takiego jak MATLAB, ale w większości środowisk zakładam, że programista wiedział, co robią. I cholera, rozpoczęcie pętli od 1 jest dość powszechne. Jest wiele powodów, aby pominąć pierwszy element czegoś.
Kat
@Kat Powód ten musi być jasny dla przyszłych czytelników. Raczej zakładam, że przyszły programista nie wie, co robi.
A1rPun
2

Wątpię, czy ktokolwiek byłby zdezorientowany tym pierwszym. Wszyscy musieliśmy to zrobić. Do tego stopnia, że ​​drugi jest znacznie bardziej zagmatwany. „Dlaczego jest tam 0+? Czy w jakiś sposób zastąpiły one operatora +?”

Przyzwoity kompilator i tak zamieni drugi na pierwszy, ale wygląda na to, że używasz PHP, które jest interpretowane. Więc za każdym razem, gdy interpreter natrafi na tę pętlę, będzie musiał dodać 0 i 1. Nie jest to wielka sprawa, ale po co zmuszać tłumacza do pracy?

Opłata Kevin
źródło
2

Użyj zmiennej, która wyjaśnia punkt początkowy.

Musisz „ pominąć pierwszy element w tablicy zerowej ”, na przykład:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}
catta
źródło
6
Lubię używać zmiennej, ale nie znoszę tej nazwy. To nie wyjaśnia, dlaczego pomijasz pierwszy element. Zresztą 1 mi to mówi. Co dobrego ma zmienna, której nazwę należy zmienić, gdy zmienia się wartość? Wiem, że OP nie dał nam pojęcia, dlaczego więc wybrać dobre imię, musisz wymyślić powód. Bez lepszego imienia wolałbym odzyskać 1.
candied_orange
@CandiedOrange Zgadzam się z tobą, że nazwa zmiennej powinna być bardziej znacząca, ale przedstawiony problem nie wyjaśnia, dlaczego chce pominąć pierwszą wartość. Chodzi mi o to, podam tylko przykład, autor może wybrać imię, które będzie dla niego najlepsze.
catta
Proszę, nie ucz tego w ten sposób. To jest dość mylące. Do wielu programistów sięgnie po najłatwiejszą możliwą nazwę, aby mogli wrócić do pisania trudnego do zrozumienia kodu. Poważnie, wolę poradzić sobie z 1 niż z tym.
candied_orange
1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Jeśli ktoś ma obsesję na punkcie wszystkich pętli zaczynających się od zera, można użyć instrukcji kontynuacji. Dodaj komentarz, dlaczego pomijasz, ponieważ normalnie nie.

Jon Raynor
źródło
2
Problem z tą opcją oznacza, że ​​będziemy to oceniać dla każdego elementu, dodając n dodatkowych porównań do pętli, po prostu pomijając pierwszy z innych metod (przesunięcie tablicy, zaczynając od i = 1, cokolwiek ) oznacza wykonywanie tylko pracy, której potrzebujesz.
Kevin Fee
3
@KevinFee Jeśli nie masz do czynienia z ogromnymi tablicami, powiedziałbym, że to proste porównanie nie będzie problemem. I podoba mi się wyraźność if first then skipkomentarza, który mówi dlaczego. Wciąż bez kontekstu żadne z rozwiązań nie jest „najlepsze”
Ivan Pintar
-2

Chciałbym usunąć pierwszy element przed zapętleniem. Utwórz nową tablicę, jeśli potrzebujesz. Wyjaśnij w komentarzu, dlaczego to robisz. A potem po prostu zrób prosty foreach.

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

W ten sposób twoje zamiary są całkowicie jasne.

W celu dalszego wyjaśnienia można zawinąć kod w metodę o odpowiedniej nazwie, aby wszystko było bardziej zrozumiałe.

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

Jednak w tym wszystkim wciąż brakuje kontekstu. Co chcesz zrobić z elementami? Czy zwrócisz nową tablicę? Czy zależy Ci na oryginale i nowej tablicy po tobie doStuff()?

W każdym razie nie ma tutaj jasnej odpowiedzi, a decyzja, jak uczynić kod czytelnym, zależy w dużej mierze od kontekstu.

Ivan Pintar
źródło
1
Podoba mi się to, ponieważ nie muszę teraz zajmować się indeksami, co zawsze jest plusem.
Tomas Zubiri,
1
Wadą jest to, że jeśli nie chcesz efektów ubocznych, musisz skopiować całą tablicę.
Tomas Zubiri,
1
A jeśli powodem, dla którego zaczynamy od 1, jest to, że robimy $array[$i-1] = $array[$i]lub coś podobnego, zgodnie z odpowiedzią @ DocBrown?
Kevin Fee
1
To wydaje mi się okropne. Oprócz całej nieefektywności, skutków ubocznych i niemożności rozwiązania dość powszechnych przypadków użycia 1(patrz komentarz Kevina Lee), kod wcale nie czyni jaśniejszego. Czytelnik musi zrozumieć przesunięcie tablicy, co robi i jak działa. Może ten wiersz kodu jest błędem? Czy modyfikuje tablicę, czy zwraca nową? Czy wstawia element, czy go usuwa? Czy to zmienia wskaźniki, czy nie? Nie widzę, jak użycie pętli opartej na jednym nie byłoby ogromnym ulepszeniem tej funkcji (i biorąc pod uwagę jej nazwę, natychmiast zrozumiałe).
Eiko,
1
Odpowiedzi na te pytania w dużym stopniu zależą od kontekstu. A jeśli chodzi o efektywność, przyjąłbym foreach na każdy dzień ... Każda różnica w wydajności jest prawie niewidoczna w większości przypadków.
Ivan Pintar,