forループに基づくインデックスの最初の要素をスキップする明確な方法


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 2016年

7
私はおそらく最初のオプションに行き、最初の要素をスキップする必要がある理由を説明するコメントを追加します。
Vincent Savard、2016年

3
クリアネスは私が目指しているものです、私は質問を編集しました。それはもっとはっきりしていますか?
Tomas Zubiri 2016年

10
PHPを使用しない方が優れた方法です。
猫、

3
PHPにはforeachコンストラクトがありますか?あなたはそうすることができますforeach ($i in range(1, count))(それはPHPでどのように見えるものでも)。またはforeach ($item in array.skip(1))、C#の人が行うようなものです。
usr

回答:


23

どちらも嫌いです。

マジックナンバーを使用できると誰が言ったのですか。オフセット1から開始する場合は、オフセット1から開始する理由を教えてください。同様に魔法のゼロを追加しても、何も説明されません。

これはペイロードオフセットですか?これは、nullで終了するc文字列に変換するパスカル文字列ですか?何が起こっているのか教えてください。

申し訳ありませんが、私はこのような無意味な謎を解読する私のキャリアの多くを無駄にしており、それらに対する私の忍耐は薄れていきました。きちんとした名前の変数は本当に尋ねるべきですか?

まともな名前とは、最初の要素をスキップする理由を説明する名前です。最初の要素をスキップしているという単純なことではありません。その1は私にそれ自身のものだと私に言った。


19
0と1はマジックナンバーではありません。
user949300

19
@ user949300ああ、確かに彼らはここにいます。それらは時々不思議ではない単なる数字です。2が常にマジックナンバーであるからといって、1がマジックナンバーであるとは限りません。魔法は意味の欠如から来ています。ここで1オフセットで始まるとはどういう意味ですか?ここで0を追加するとどのようなメリットがありますか?ああそう、これらの数字は確かに魔法のようです。ピクシーダストが滴り落ちるのが見えます。
candied_orange 2016年

4
もちろん、static final int LONELIEST_NUMBER = 1すべてのJavaコードで定義を開始します。:-)とはいえ、さらに考えたところ、回答の投票を取り消すことを希望しますが、編集しない限りできません。愚かなSOルール?
user949300

6
@英子:ループが2番目の要素から始まる理由が説明されていない場合、一部のメンテナンスプログラマーが最初の要素から始まるようにループを変更することが実質的に保証されます。そのため、この文脈では、数字の1はマジックナンバーです。
Bart van Ingen Schenau

2
@BartvanIngenSchenauコンテキスト内にすぐに目に見える理由があると思いました。要素をその前の要素と比較するように(1から始めるのが最も頻繁に使用されると考えられていました。ここでは、有用な定数名を確認できませんでした)。最初の要素に特別な意味がある場合、デザインが壊れている可能性があり、そのインデックスに名前を付けるよりも適切な修正が必要です。ここに変数を導入する理由は決してないとは言いません。これらのケースが非常にまれである(またはおそらくそうでなければならない)と私が思うだけです。
Eiko

12

短い答え:最初のオプションの方が優れています。

2番目のオプションはノイズを追加するだけです。0 + 1が0であった可能性があることを読者が理解するのに役立つ可能性は非常に低いですが、0である可能性は1です。特に、すべての配列が0から始まる言語では。

他にも述べたように、ループが0ではなく1から始まるという事実を強調したい場合は、コメントを追加してください。


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

あなたの例は不自然に見えます。実際のコードでは、ループが2番目の配列要素から始まる必要があるという事実は、おそらく次のコード行から明らかです。たとえば、実際のコードが次のようになっている場合

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

ループが0ではなく1から始まる理由を明確にするために必要な説明や「0 + 1」構成はありません。

ただし、ループ内のコードがそのような明白な方法で理由を説明していない場合(おそらくarray[0]特別な意味があり、残りの要素とは異なる方法で処理する必要がある)、説明コメントを追加します。ただし、これを行う前に、array[0]この特別な意味を持たないようにしてよく考え、周囲のコードを再編成してください。


サンプルコードのような状況では、変数に「oneBasedIndex」または「zeroBasedIndex」という名前を付けます。そのタスクにもっと具体的なものがより良いでしょうが。
user949300

5

オプション#2を見たことはありませんが、私はそれが好きです。どうして?オプション#1を使用すると、配列が0から始まることをプログラマが忘れたかどうか疑問に思います。オプション#2を使用すると、それらが意図的に1から始まることが明確になります。

とはいえ、どちらの場合でも、コメントを追加して、要素をスキップする理由を確認してください。

または、1から始める理由を簡単に説明できる場合は、定数を使用します。たとえば、コマンドライン引数を見ると、次のようになります。

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

個人的には、おそらく代わりにコメントを使用します、YMMV。


初心者を扱う環境以外では、配列がゼロから始まることを同僚が忘れてしまうという問題は一度もありませんでした。あなたの仕事でもMATLABのような言語を使用している場合は、それが起こるのを見ることができますが、ほとんどの環境では、プログラマーが何をしているか知っていると思います。そして、いや、1からループを開始するのはかなり一般的です。何かの最初の要素をスキップする理由はかなりあります。
2016年

@Katその理由は、将来の読者のために明確にする必要があります。私はむしろ将来のプログラマーがそれが何をしているのか知らないのだと思います。
A1rPun

2

誰もが最初のものに混乱することはないと思います。私たちは皆それをしなければなりませんでした。2つ目は混乱する可能性が高くなるほどで​​す。「なぜそこに0+があるのですか?どういうわけか+演算子をオーバーライドしましたか?」

まともなコンパイラーはとにかく2番目のものを最初のものに変えますが、解釈されているPHPを使用しているようです。したがって、インタープリターがそのループにヒットするたびに、実際には0と1を追加する必要があります。大したことではありませんが、なぜインタープリターに機能を実行させるのでしょうか。


2

開始点を説明する変数を使用します。

ゼロベースの配列の最初の要素をスキップする」必要があるので、たとえば次のようにします。

skipFirstElement = 1;

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

6
変数を使用するのが好きですが、この名前は嫌いです。最初の要素をスキップする理由は説明されていません。1はとにかくそれを教えてくれます。値が変更されたときに名前を変更する必要がある変数は何ですか?OPがなぜ私たちに理由を与えなかったのか知っているので、良い名前を選ぶには理由を作らなければならないでしょう。より良い名前がなければ、私はむしろ1つの背中を持っていると思います。
candied_orange 2016年

@CandiedOrange変数名の方が意味があるはずだと私は同意しますが、表示されている問題は、最初の値をスキップする理由を説明していません。私の要点は、私は例を挙げているだけです。作者は彼に最適な名前を​​選択できます。
catta 2016年

このように教えないでください。これは十分に混乱しています。多くのコーダーにとって、彼らができる最も簡単な名前に手を伸ばすので、理解しにくいコードを書き直すことができます。真剣に、私はこれよりもむしろ1を扱いたいと思います。
candied_orange 2016年

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

すべてのループがゼロから始まることにこだわっている場合は、continueステートメントを使用できます。通常はスキップしないので、スキップする理由にコメントを追加します。


2
このオプションの問題は、すべての単一の要素についてこれを評価し、ループにn個の追加の比較を追加する一方で、他の方法で最初のものをスキップすることを意味します(配列をシフトし、i = 1から開始します) )は、必要な作業のみを実行することを意味します。
Kevin Fee

3
@KevinFee大規模な配列を扱っていない場合、この単純な比較は問題にならないと思います。そして、私はそのif first then skip理由を説明するコメントの明示性が非常に好きです。それでもコンテキストがない場合、
どの

-2

ループする前に最初の要素を削除します。必要に応じて、新しい配列を作成します。コメントでその理由を説明してください。そして、単純な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
}

この方法であなたの意図は完全に明確です。

さらに明確にするために、コードを適切な名前でメソッドにラップして、物事をより明確にすることができます。

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

ただし、これらすべてにはまだコンテキストがありません。要素をどのように処理しますか?新しいアレイを返却しますか?元のアレイと新しいアレイが気になりますdoStuff()か?

とにかく、ここでは明確な答えはありません。コードを読みやすくする方法の決定は、コンテキストに大きく依存します。


1
今はインデックスを処理する必要がないため、これが好きです。これは常にプラスです。
Tomas Zubiri 2016年

1
ここでの欠点は、副作用が必要ない場合は、配列全体をコピーする必要があることです。
Tomas Zubiri 2016年

1
そして、私たちが1から始めている理由が、$array[$i-1] = $array[$i]@ DocBrownの回答のように、私たちがやっていること、または類似した何かのためである場合はどうなりますか?
Kevin Fee

1
これは私には恐ろしいようです。すべての非効率性、副作用、および一般的なユースケースを解決できないこと1(Kevin Leeのコメントを参照)の他に、コードがまったく明確になりません。読者は、array_shift、それが何をするか、どのように機能するかを理解する必要があります。たぶん、このコード行はバグですか?配列を変更するか、新しい配列を返しますか?要素を挿入したり、要素を削除したりしますか?指標が変わるのか?私は1ベースのループを使用することはないだろうかを確認するために失敗する巨大な(瞬時に理解し、その名前を与えられた)その機能の改善。
Eiko

1
これらの質問に対する答えは、状況に大きく依存します。そして、効率に関しては、私はいつでもforeachを実行します...ほとんどの場合、パフォーマンスの違いはほとんど目に見えません。
Ivan Pintar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.