Manière claire d'ignorer le premier élément d'un index basé sur une boucle

9

J'ai une boucle for où je dois ignorer le premier élément d'un tableau à base zéro.

Laquelle de ces propositions montre plus clairement mes intentions?

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

ou

for($i=0+1 ; $i < count(array) ; $i++){
    array[$i];
}
Tomas Zubiri
la source
28
Ni l'un ni l'autre $i=2-1n'est la voie supérieure. : /
yannis
7
J'irais probablement pour la première option et ajouterais un commentaire pour expliquer pourquoi le premier élément doit être ignoré.
Vincent Savard
3
La clarté est ce que je vise, j'ai édité la question. Est-ce que c'est plus clair?
Tomas Zubiri
10
Ne pas utiliser PHP est la meilleure façon.
chat
3
PHP a-t-il une construction foreach? Vous pourriez faire foreach ($i in range(1, count))(tout ce qui ressemble à PHP). Ou quelque chose comme foreach ($item in array.skip(1))ce que ferait une personne C #.
usr

Réponses:

23

Je déteste les deux.

Qui a dit que vous pouviez utiliser des nombres magiques? Si vous commencez avec un décalage de 1, pourquoi ne pas nous dire POURQUOI vous commencez avec un décalage de 1. L'ajout d'un zéro tout aussi magique ne m'explique rien.

Est-ce le décalage de la charge utile? S'agit-il d'une chaîne pascale que vous convertissez en chaîne c terminée par null? Veuillez nous dire ce qui se passe.

Désolé, mais j'ai gaspillé une grande partie de ma carrière à décoder des mystères inutiles comme celui-ci et ma patience pour eux s'est épuisée. Une variable avec un nom décent est-elle vraiment trop demander?

Par nom décent, je veux dire un nom qui explique POURQUOI nous sautons le premier élément. Pas quelque chose qui dit simplement que nous sautons le premier élément. Le 1 m'a dit ça tout seul.

candied_orange
la source
20
0 et 1 ne sont pas des nombres magiques.
user949300
19
@ user949300 Oh, ils sont certainement là. Ce sont tout simplement des nombres qui ne sont parfois pas magiques. Ce n'est pas parce que 2 est toujours un nombre magique que 1 n'est jamais un nombre magique. La magie vient du sens manquant. Que signifie le fait de commencer avec un décalage de 1 ici? À quoi sert d'ajouter un 0 ici? Oh oui, ces chiffres sont certainement magiques ici. Je peux voir la poussière de lutin en couler.
candied_orange
4
Bien sûr, je vais commencer à définir static final int LONELIEST_NUMBER = 1dans tout mon code Java. :-) Cela dit, après réflexion, j'aimerais revenir sur votre réponse, mais je ne peux pas sauf si vous la modifiez. Règle stupide de SO?
user949300
6
@Eiko: S'il n'y a aucune explication pour laquelle la boucle démarre au deuxième élément, il est pratiquement garanti que certains programmeurs de maintenance changeront la boucle pour démarrer au premier élément. C'est pourquoi le chiffre 1 est un nombre magique dans ce contexte.
Bart van Ingen Schenau
2
@BartvanIngenSchenau J'ai supposé qu'il y aurait une raison immédiatement visible dans le contexte. Comme comparer des éléments avec leurs prédécesseurs (que je pensais être le cas d'utilisation le plus fréquent pour commencer à 1 - et je ne vois aucun nom de constante utile ici). Si le premier élément a une signification ultra spéciale, la conception peut être rompue et il devrait y avoir de meilleures corrections que de nommer cet index. Je ne dis pas qu'il n'y a jamais de raison d'introduire une variable ici. C'est juste que je pense que ces cas sont (ou devraient seulement être) très rares.
Eiko
12

Réponse courte: la première option est meilleure.

La deuxième option ajoute simplement du bruit. Il est très peu probable que 0 + 1 aide le lecteur à comprendre qu'il aurait pu être 0, mais c'est 1. Il est beaucoup plus probable qu'il sera perplexe un court instant et distrait de ce que la boucle représente. Surtout dans une langue où tous les tableaux commencent à 0.

Comme d'autres l'ont mentionné, si vous voulez souligner le fait que la boucle commence à 1, pas à 0, ajoutez simplement un commentaire.

Florian F
la source
10

Ne nous dites pas que vous sautez le premier élément - nous pouvons le voir. Ce qui n'est pas évident, c'est pourquoi . Alors .. si ce n'est pas évident d'après le contexte, dites-nous pourquoi:

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

Ou, si vous êtes opposé aux commentaires, quelque chose comme:

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

N'utilisez pas de commentaires et de ruse pour nous rappeler le fonctionnement de la langue.

svidgen
la source
6

Votre exemple semble artificiel. Dans le code du monde réel, le fait que les boucles doivent commencer au deuxième élément du tableau est très probablement évident à partir des lignes de code suivantes. Par exemple, si le vrai code ressemble à ceci

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

il n'y aurait aucune explication ou construction "0 + 1" nécessaire pour expliquer pourquoi la boucle commence à 1 au lieu de 0.

Cependant, si le code à l'intérieur de la boucle n'explique pas les raisons de manière aussi évidente (peut-être array[0]a une signification spéciale et doit être traité différemment des autres éléments), ajoutez un commentaire explicatif. Mais avant de faire cela, réfléchissez-y à deux fois si vous pouvez éviter d'avoir array[0]cette signification spéciale et réorganisez le code environnant, ce qui serait probablement la meilleure alternative.

Doc Brown
la source
Dans des situations comme votre exemple de code, j'aime nommer les variables "oneBasedIndex" ou "zeroBasedIndex". Bien que quelque chose d'encore plus spécifique pour cette tâche serait mieux.
user949300
5

Jamais vu l'option n ° 2, mais j'aime ça. Pourquoi? Avec l'option # 1, je me demande si le programmeur a oublié que les tableaux commencent à 0. L'option # 2 rend plus clair qu'ils commencent délibérément à 1.

Cela dit, il vaut mieux dans les deux cas ajouter un commentaire expliquant pourquoi vous sautez l'élément.

Ou, si vous pouvez facilement décrire pourquoi vous commencez à un, utilisez une constante. Par exemple, si vous regardez des arguments de ligne de commande, quelque chose comme

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

Personnellement, j'utiliserais probablement un commentaire à la place, YMMV.

user949300
la source
Je dirai qu'en dehors des environnements où vous avez affaire à des débutants, je n'ai jamais eu le problème de collègues oubliant que les tableaux commencent à zéro. Je pouvais voir cela se produire si votre travail utilisait également un langage comme MATLAB, mais dans la plupart des environnements, je suppose que le programmeur savait ce qu'il faisait. Et diable, commencer une boucle à 1 est sacrément commun. Il y a plusieurs raisons de sauter le premier élément de quelque chose.
Kat
@Kat Cette raison doit être claire pour les futurs lecteurs. Je préfère supposer qu'un futur programmeur ne sait pas ce qu'il fait.
A1rPun
2

Je doute que quiconque soit dérouté par le premier. Nous avons tous dû le faire. Tant et si bien que le second est beaucoup plus susceptible de confondre. "Pourquoi y a-t-il un 0+? Ont-ils outrepassé l'opérateur + d'une manière ou d'une autre?"

Un compilateur décent transformera le second en premier de toute façon, mais il semble que vous utilisez PHP, qui est interprété. Donc, à chaque fois que l'interprète frappe cette boucle, il va falloir ajouter 0 et 1. Ce n'est pas grave, mais pourquoi faire faire le travail à l'interprète?

Kevin Fee
la source
2

Utilisez une variable qui explique le point de départ.

Vous devez " ignorer le premier élément d'un tableau à base zéro ", par exemple:

skipFirstElement = 1;

for($i=$skipFirstElement ; $i < count(array) ; $i++){
    array[$i];
}
catta
la source
6
J'aime utiliser une variable mais je déteste ce nom. Cela n'explique pas POURQUOI vous sautez le premier élément. Un 1 me le dit de toute façon. À quoi sert une variable qui doit être renommée lorsqu'elle change de valeur? Je sais que le PO ne nous a donné aucune idée pourquoi, alors pour choisir un bon nom, vous devrez trouver une raison. Sans un meilleur nom, je préfère avoir le 1 de retour.
candied_orange
@CandiedOrange Je suis d'accord avec vous que le nom de variable devrait être plus significatif, mais le problème tel qu'il est présenté n'explique pas pourquoi il veut ignorer la première valeur. Mon point est, je donne juste un exemple, l'auteur peut choisir un nom qui lui convient le mieux.
catta
Veuillez ne pas enseigner de cette façon. C'est assez déroutant. Pour de nombreux codeurs, ils trouveront le nom le plus simple possible afin de pouvoir recommencer à écrire du code difficile à comprendre. Sérieusement, je préfère m'occuper du 1 que de celui-ci.
candied_orange
1
//We are skipping the first element because...    
if ($i==0)  
{    continue;      } 

Si l'un est obsédé par toutes les boucles commençant à zéro, vous pouvez utiliser une instruction continue. Ajoutez un commentaire à la raison pour laquelle vous sautez, car normalement, vous ne le feriez pas.

Jon Raynor
la source
2
Le problème avec cette option signifie que nous allons évaluer cela pour chaque élément, en ajoutant n comparaisons supplémentaires à la boucle, tout en sautant simplement la première par une autre méthode (en décalant le tableau, en commençant par i = 1, peu importe ) signifie uniquement faire le travail dont vous avez besoin.
Kevin Fee
3
@KevinFee Si vous ne traitez pas avec des tableaux massifs, je dirais que cette simple comparaison ne sera pas un problème. Et j'aime beaucoup l'explicitation de if first then skipavec un commentaire disant pourquoi. Toujours sans contexte, aucune des solutions n'est "la meilleure"
Ivan Pintar
-2

Ce que je ferais, c'est supprimer le premier élément avant de boucler. Créez un nouveau tableau si vous en avez besoin. Expliquez dans un commentaire pourquoi vous le faites. Et puis faites juste un simple 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
}

De cette façon, votre intention est parfaitement claire.

Pour clarifier davantage, vous pouvez envelopper le code dans une méthode avec un nom approprié pour rendre les choses plus claires.

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

Cependant, tout cela manque encore de contexte. Que voulez-vous faire avec les éléments? Retournerez-vous le nouveau tableau? Vous souciez-vous de l'original et du nouveau tableau après vous doStuff()?

Quoi qu'il en soit, il n'y a pas de réponse claire ici, et décider comment rendre le code lisible dépend grandement du contexte.

Ivan Pintar
la source
1
J'aime ça parce que je n'ai pas besoin de gérer les index maintenant, ce qui est toujours un plus.
Tomas Zubiri
1
L'inconvénient ici est que si vous ne voulez pas d'effets secondaires, vous devez copier l'ensemble du tableau.
Tomas Zubiri
1
Et si la raison pour laquelle nous commençons à 1 est parce que nous faisons $array[$i-1] = $array[$i]ou quelque chose de similaire, selon la réponse de @ DocBrown?
Kevin Fee
1
Cela me semble horrible. Outre toute l'inefficacité, les effets secondaires et l'incapacité à résoudre des cas d'utilisation assez courants 1(voir le commentaire de Kevin Lee), cela ne rend pas le code plus clair du tout. Le lecteur doit comprendre array_shift, ce qu'il fait, comment cela fonctionne. Peut-être que cette ligne de code est un bug? Modifie-t-il le tableau ou en renvoie-t-il un nouveau? Insère-t-il un élément ou en supprime-t-il un? Change-t-il ou non les indices? Je ne vois pas comment l'utilisation d'une boucle à base unique ne serait pas une énorme amélioration de cette fonction (et étant donné son nom, instantanément compréhensible).
Eiko
1
Les réponses à ces questions dépendent fortement du contexte. Et en ce qui concerne l'efficacité, je prendrais un foreach pour n'importe quel jour ... Toute différence de performance est presque invisible dans la plupart des cas.
Ivan Pintar