Objective-CとPHPの高速列挙(foreach文)は順番(参照順序)が保証される
高速列挙の順番(参照順序)の保証についてです。
最近この件でブログに来られる方が多いみたいなのでもう一度整理してみます。
高速列挙とはリストやハッシュテーブルなどのデータ構造の各要素に対して与えられた文の実行を繰り返すというループを記述するための文です。
foreach文と呼ばれることもあります。
記述が簡単で普通のループ文(for文)より高速に動作するため多用したくなるのですが、注意しなければならないのは必ずしも順番(参照順序)が保証されない点です。
例えば配列の値を添え字(インデックス)の順に+1ずつ加算していきたいような場合順番が保証されないと意味がありません。
順番が保証されるかはプログラミング言語によって異なります。
複数の言語を使う場合とても紛らわしい話です。
ここでてぃーがよく使うプログラミング言語(Objective-C、PHP、Visual Basic、Visual C#)の高速列挙の順番(参照順序)の保証をまとめてみると次のようになります。

つまりObjective-CとPHPの高速列挙は順番(参照順序)が保証されます。
ただしすべて保証されるわけではないので注意です。(下記参照)
保証される根拠
ネットでは情報が錯綜していてObjective-CもPHPも高速列挙の順番は保証されないというデマ?もあり、よけいに混乱しますね(><)
Objective-CとPHPについて根拠を挙げます。
Objective-C
てぃーが以前勉強していたアップル公式の「Objective-Cプログラミング言語」にあります。→【勉強】Objective-Cプログラミング言語(その4/最終回)+おすすめの本
高速列挙の使用(98ページより)
明確な順序を持つコレクションや列挙子(配列から派生したNSArrayインスタンスやNSEnumeratorインスタンス)の場合、列挙はその順序に従って行われるため、必要な場合は反復をカウントするだけでコレクション内を指す正しいインデックスが得られます。
またiOS Developer LibraryのFast Enumerationの項目にも同様の記述があります。
(英語ですが)
→The Objective-C Programming Language: Fast Enumeration
Using Fast Enumeration
For collections or enumerators that have a well-defined order—such as an NSArray or an NSEnumerator instance derived from an array—the enumeration proceeds in that order, so simply counting iterations gives you the proper index into the collection if you need it.
つまりNSArray、NSMutableArray、NSEnumeratorなどは順番が保証されますが、NSDictionaryなどは保証されないということです。
PHP
こちらも公式のページにあります。→PHP: foreach - Manual
「使用法を示すためにその他の例を示します。」の16行目(空行含む)
foreach ($a as $v) {
echo "\$a[$i] => $v.\n";
$i++;
}
なおこの根拠についてはTwitterで@omochimetaruさんに教えていただきました。
ありがとうございました。
@teapipin phpの連想配列はペアが順番を保持しますよ
— おさわりまんこさん (@omochimetaru) 8月 18, 2012
(中略)
@omochimetaru おお! echo "\$a[$i] => $v.\n"; ときちんと順番が保証されることが分かるように書かれていますね。本家のマニュアルをじっくり読むべきでした。ありがとうございます。
— てぃー:アプリ開発、分析屋、魔法少女さん (@teapipin) 8月 18, 2012
↓この記事が参考になったら拍手、ツイート、いいね、はてブ、いずれかをお願いします。今後のブログ作りに役立てたいので。
- 関連記事
-
- Objective-CとPHPの高速列挙(foreach文)は順番(参照順序)が保証される (2012/11/18)
- 【Objective-C】iPhoneの言語設定を取得する方法(ローカリゼーション(ローカライズ)もこれでカバー!) (2012/04/23)
- 【Objective-C】文字列(NSString)の先頭、末尾の確認方法(~で始まる、~で終わる) (2011/12/17)
- 【Objective-C】文字列(NSString)の大文字と小文字を区別せずに比較する方法 (2011/12/17)
- 【Objective-C】配列(NSArray、NSMutableArray)の要素(値)をランダムに並べ替える方法 (2011/12/17)