Klare Möglichkeit, das erste Element in einem Index zu überspringen, der auf der Schleife basiert


9

Ich habe eine for-Schleife, in der ich das erste Element in einem nullbasierten Array überspringen muss.

Welche davon zeigt meine Absichten deutlicher?

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

oder

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

28
Weder $i=2-1ist der überlegene Weg. : /
Yannis

7
Ich würde wahrscheinlich die erste Option wählen und einen Kommentar hinzufügen, um zu erklären, warum das erste Element übersprungen werden muss.
Vincent Savard

3
Klarheit ist das, was ich anstrebe, ich habe die Frage bearbeitet. Ist das klarer?
Tomas Zubiri

10
PHP nicht zu verwenden ist der überlegene Weg.
Katze

3
Hat PHP ein foreach-Konstrukt? Sie könnten tun foreach ($i in range(1, count))(wie auch immer das in PHP aussieht). Oder so etwas foreach ($item in array.skip(1))würde eine C # -Person tun.
usr

Antworten:


23

Ich hasse beide.

Wer hat gesagt, Sie könnten magische Zahlen verwenden? Wenn Sie mit einem Versatz von 1 beginnen, sagen Sie uns, WARUM Sie mit einem Versatz von 1 beginnen. Das Hinzufügen einer ebenso magischen Null erklärt mir nichts.

Ist das der Nutzlastoffset? Handelt es sich um eine Pascal-Zeichenfolge, die Sie in eine nullterminierte c-Zeichenfolge konvertieren? Bitte sagen Sie uns, was los ist.

Tut mir leid, aber ich habe viel Zeit meiner Karriere damit verschwendet, sinnlose Geheimnisse wie dieses zu entschlüsseln, und meine Geduld für sie hat nachgelassen. Ist eine Variable mit einem anständigen Namen wirklich zu viel verlangt?

Mit anständigem Namen meine ich einen Namen, der erklärt, WARUM wir das erste Element überspringen. Nicht etwas, das einfach sagt, dass wir das erste Element überspringen. Die 1 hat mir das alleine gesagt.


19
0 und 1 sind keine magischen Zahlen.
user949300

19
@ user949300 Oh, sie sind auf jeden Fall hier. Es sind einfach Zahlen, die gelegentlich nicht magisch sind. Nur weil 2 immer eine magische Zahl ist, heißt das nicht, dass 1 niemals eine magische Zahl ist. Die Magie kommt von fehlender Bedeutung. Was zum Teufel bedeutet hier ab einem 1-Offset? Was nützt das Hinzufügen einer 0 hier? Oh ja, diese Zahlen sind hier sicherlich magisch. Ich kann sehen, wie der Elfenstaub von ihnen tropft.
candied_orange

4
Klar, ich werde anfangen, static final int LONELIEST_NUMBER = 1meinen gesamten Java-Code zu definieren. :-) Das heißt, nach weiteren Überlegungen möchte ich Ihre Antwort rückgängig machen, kann es aber nicht, es sei denn, Sie bearbeiten sie. Dumme SO-Regel?
user949300

6
@Eiko: Wenn es keine Erklärung gibt, warum die Schleife beim zweiten Element beginnt, ist praktisch garantiert, dass einige Wartungsprogrammierer die Schleife so ändern, dass sie beim ersten Element beginnt. Deshalb ist die Ziffer 1 in diesem Zusammenhang eine magische Zahl.
Bart van Ingen Schenau

2
@BartvanIngenSchenau Ich nahm an, dass es einen sofort sichtbaren Grund im Kontext geben würde. Als würde man Elemente mit ihren Vorgängern vergleichen (was ich für den häufigsten Anwendungsfall hielt, um bei 1 zu beginnen - und ich sehe hier keinen nützlichen konstanten Namen). Wenn das erste Element eine ganz besondere Bedeutung hat, ist das Design möglicherweise fehlerhaft, und es sollte bessere Korrekturen geben, als diesen Index zu benennen. Ich sage nicht, dass es hier nie einen Grund gibt, eine Variable einzuführen. Es ist nur so, dass ich denke, dass diese Fälle sehr selten sind (oder vielleicht nur sein sollten).
Eiko

12

Kurze Antwort: Die erste Option ist besser.

Die zweite Option fügt nur Rauschen hinzu. Es ist sehr unwahrscheinlich, dass 0 + 1 dem Leser hilft zu verstehen, dass es 0 gewesen sein könnte, aber es ist 1. Viel wahrscheinlicher ist es, dass er einen kurzen Moment verwirrt und von dem abgelenkt wird, worum es in der Schleife geht. Besonders in einer Sprache, in der alle Arrays bei 0 beginnen.

Wie bereits erwähnt, fügen Sie einfach einen Kommentar hinzu, wenn Sie die Tatsache betonen möchten, dass die Schleife bei 1 und nicht bei 0 beginnt.


10

Sagen Sie uns nicht, dass Sie den ersten Artikel überspringen - das können wir sehen. Was nicht offensichtlich ist, ist warum . Also ... wenn es aus dem Kontext nicht ersichtlich ist, sagen Sie uns warum:

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

Oder, wenn Sie kommentaravers sind, so etwas wie:

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

Verwenden Sie keine Kommentare und Tricks, um uns daran zu erinnern, wie die Sprache funktioniert.


6

Ihr Beispiel sieht erfunden aus. Im Code der realen Welt ist die Tatsache, dass die Schleifen beim zweiten Array-Element beginnen müssen, höchstwahrscheinlich aus den folgenden Codezeilen ersichtlich. Zum Beispiel, wenn der echte Code so aussieht

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

Es wäre keine Erklärung oder kein "0 + 1" -Konstrukt erforderlich, um zu verdeutlichen, warum die Schleife bei 1 statt bei 0 beginnt.

Wenn der Code in der Schleife die Gründe jedoch nicht so offensichtlich erklärt (möglicherweise array[0]eine besondere Bedeutung hat und anders behandelt werden muss als die übrigen Elemente), fügen Sie einen erklärenden Kommentar hinzu. Aber bevor Sie dies tun, überlegen Sie zweimal, ob Sie array[0]diese besondere Bedeutung vermeiden können , und organisieren Sie den umgebenden Code neu, was wahrscheinlich die bessere Alternative wäre.


In Situationen wie Ihrem Beispielcode möchte ich die Variablen "oneBasedIndex" oder "zeroBasedIndex" nennen. Obwohl etwas noch Spezifischeres für diese Aufgabe besser wäre.
user949300

5

Ich habe Option 2 noch nie gesehen, aber ich mag es. Warum? Mit Option 1 würde ich mich fragen, ob der Programmierer vergessen hat, dass Arrays bei 0 beginnen. Option 2 macht klarer, dass sie absichtlich bei 1 beginnen.

Das heißt, am besten in jedem Fall einen Kommentar hinzufügen, warum Sie Element überspringen.

Wenn Sie leicht beschreiben können, warum Sie bei eins beginnen, verwenden Sie eine Konstante. Wenn Sie sich beispielsweise Befehlszeilenargumente ansehen, so etwas wie

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

Persönlich würde ich wahrscheinlich stattdessen nur einen Kommentar verwenden, YMMV.


Ich werde sagen, dass ich außerhalb von Umgebungen, in denen Sie mit Anfängern zu tun haben, nie das Problem hatte, dass Mitarbeiter vergessen, dass Arrays bei Null beginnen. Ich könnte es sehen, wenn Ihre Arbeit auch eine Sprache wie MATLAB verwendet, aber in den meisten Umgebungen würde ich davon ausgehen, dass der Programmierer wusste, was sie taten. Und zum Teufel, eine Schleife bei 1 zu starten, ist verdammt üblich. Es gibt einige Gründe, das erste Element von etwas zu überspringen.
Kat

@Kat Dieser Grund muss für zukünftige Leser klar sein. Ich würde eher annehmen, dass ein zukünftiger Programmierer nicht weiß, was er tut.
A1rPun

2

Ich bezweifle, dass jemand von dem ersten verwirrt wäre. Wir mussten es alle tun. So sehr, dass der zweite viel eher verwirrt. "Warum gibt es dort eine 0+? Haben sie den Operator + irgendwie überschrieben?"

Ein anständiger Compiler verwandelt den zweiten ohnehin in den ersten, aber es sieht so aus, als würden Sie PHP verwenden, das interpretiert wird. Jedes Mal, wenn der Interpreter diese Schleife erreicht, muss er tatsächlich 0 und 1 addieren. Keine große Sache, aber warum sollte der Interpreter die Arbeit machen?


2

Verwenden Sie eine Variable, die den Startpunkt erklärt.

Sie müssen " das erste Element in einem nullbasierten Array überspringen ", also zum Beispiel:

skipFirstElement = 1;

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

6
Ich benutze gerne eine Variable, aber ich hasse diesen Namen. Es erklärt nicht, WARUM Sie das erste Element überspringen. Eine 1 sagt mir das sowieso. Was nützt eine Variable, die umbenannt werden muss, wenn sich ihr Wert ändert? Ich weiß, das OP hat uns keine Ahnung gegeben, warum Sie sich einen Grund ausdenken müssen, um einen guten Namen zu wählen. Ohne einen besseren Namen hätte ich lieber die 1 zurück.
candied_orange

@CandiedOrange Ich stimme Ihnen zu, dass der Variablenname aussagekräftiger sein sollte, aber das Problem, wie es dargestellt wird, erklärt nicht, warum er den ersten Wert überspringen möchte. Mein Punkt ist, ich gebe nur ein Beispiel, der Autor kann einen Namen wählen, der für ihn am besten ist.
Catta

Bitte unterrichte nicht so. Das ist verwirrend genug. Viele Programmierer werden nach dem einfachsten Namen greifen, den sie können, damit sie wieder schwer verständlichen Code schreiben können. Im Ernst, ich würde mich lieber mit der 1 befassen als mit dieser.
candied_orange

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

Wenn man von allen Schleifen besessen ist, die bei Null beginnen, können Sie eine continue-Anweisung verwenden. Fügen Sie einen Kommentar hinzu, warum Sie überspringen, da dies normalerweise nicht der Fall ist.


2
Das Problem mit dieser Option bedeutet, dass wir dies für jedes einzelne Element auswerten und der Schleife n zusätzliche Vergleiche hinzufügen, während wir einfach den ersten durch eine andere Methode überspringen (Verschieben des Arrays, beginnend mit i = 1, was auch immer) ) bedeutet, nur die Arbeit zu erledigen, die Sie benötigen.
Kevin Fee

3
@ KevinFee Wenn Sie nicht mit massiven Arrays zu tun haben, würde ich sagen, dass dieser einfache Vergleich kein Problem darstellt. Und ich mag die if first then skipAussage mit einem Kommentar, warum. Noch ohne Kontext ist keine der Lösungen "am besten"
Ivan Pintar

-2

Was ich tun würde, ist das erste Element vor dem Schleifen zu entfernen. Erstellen Sie bei Bedarf ein neues Array. Erklären Sie in einem Kommentar, warum Sie es tun. Und dann machen Sie einfach einen einfachen 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
}

Auf diese Weise ist Ihre Absicht völlig klar.

Zur weiteren Verdeutlichung können Sie den Code in eine Methode mit einem geeigneten Namen einschließen, um die Dinge klarer zu machen.

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

All dies fehlt jedoch immer noch der Kontext. Was willst du mit den Elementen machen? Werden Sie das neue Array zurückgeben? Interessieren Sie sich für das ursprüngliche und das neue Array nach Ihnen?doStuff() ?

Auf jeden Fall gibt es hier keine klare Antwort, und die Entscheidung, wie der Code lesbar gemacht werden soll, hängt stark vom Kontext ab.


1
Ich mag das, weil ich mich jetzt nicht mit Indizes befassen muss, was immer ein Plus ist.
Tomas Zubiri

1
Der Nachteil hierbei ist, dass Sie das gesamte Array kopieren müssen, wenn Sie keine Nebenwirkungen wünschen.
Tomas Zubiri

1
Und was ist, wenn der Grund, warum wir bei 1 beginnen, darin besteht, dass wir $array[$i-1] = $array[$i]etwas Ähnliches tun , wie in der Antwort von @ DocBrown angegeben?
Kevin Fee

1
Das scheint mir schrecklich. Abgesehen von all der Ineffizienz, den Nebenwirkungen und der Unfähigkeit, häufig auftretende Anwendungsfälle zu lösen 1(siehe Kevin Lees Kommentar), wird der Code dadurch überhaupt nicht klarer. Der Leser muss array_shift verstehen, was es tut, wie es funktioniert. Vielleicht ist diese Codezeile ein Fehler? Ändert es das Array oder gibt es ein neues zurück? Fügt es ein Element ein oder entfernt es eines? Ändert es die Indizes oder nicht? Ich kann nicht erkennen, dass die Verwendung einer einbasierten Schleife keine große Verbesserung dieser Funktion darstellt (und ihren Namen sofort verständlich macht).
Eiko

1
Die Antworten auf diese Fragen hängen stark vom Kontext ab. Und was die Effizienz angeht, würde ich für jeden Tag einen Foreach übernehmen ... Jeder Leistungsunterschied ist in den meisten Fällen nahezu unsichtbar.
Ivan Pintar
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.