忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2024/05/08 11:04 |
PHP1-53:foreachを自力で実装

PHP5にはIteratorインターフェイスというものが存在しますが、このインターフェイスを実装すると、それがそのオブジェクトのforeachの挙動になります。
http://php.benscom.com/manual/ja/class.iterator.php

適当なクラスを作成し、それに対して
foreach($MyClass as $key=>$val)
とやったときの$keyと$val、そしてその出現内容や順番なんかを自由に変更できるのです。

特に意味はありませんが、適当に文字列を突っ込んだら50音順に取り出せるクラスを作ってみます。

example_foreach.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
    
class Example_Foreach implements Iterator{
    
    //変数
        protected $words=array();    //配列入れ
        protected $current=0;        //現在値
    
    //コンストラクタ
        public function __construct(){}
    
    //追加
        public function set($word){
            $this->words[]=$word;
            sort($this->words,SORT_STRING);
        }
    
    //検索対象の全件数を返す
        public function count(){
            return count($this->words);
        }
    
    //イテレータ(foreachの実装)
        public function current(){
            return $this->words[$this->current];
        }
        public function key(){
            return $this->current;
        }
        public function next(){
            $this->current=$this->current+1;
        }
        public function valid(){
            if(isset($this->words[$this->current])){
                return true;
            }
            return false;
        }
        public function rewind(){
            $this->current=0;
        }
    
#↓クラスのおわり
}

使用時は普通にset()してforeachで取り出すだけです。

example.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
    
    require_once('example_foreach.php');
    $obj=new Example_Foreach();
    
    $obj->set('a');
    $obj->set('d');
    $obj->set('e');
    $obj->set('c');
    $obj->set('b');
    
    foreach($obj as $key=>$val){
        $ret[$key]=$val;
    }

$retはarray('a','b','c','d','e')という配列になります。
Example_Foreachには他にも$currentという変数や幾つかのメソッドがあるのに、それは無視されて、$wordsの中身だけが返ってきます。
Iteratorインターフェイスに存在するcurrent()、key()、next()、valid()、rewind()の各メソッドを実装することで、foreachの挙動を変更することができました。

ここでは単純に小さい順に取り出しましたが、メソッドを変更することで順番を変更したり、返り値を文字列以外のものにしたりといったことが自由に行えます。
ただ注意事項として、うっかり変な実装をすると、特にnextあたりを間違えると容易に無限ループになってしまうので気をつけましょう。
next(){}とかやってしまうとブラウザが死にます。

まあ、この程度ならいちいちオブジェクトにせず、配列に入れてsortした方が早い(というかIteratorが遅い)というのは秘密だ。

 

PR


2009/02/16 11:52 | Comments(0) | TrackBack() | PHP

トラックバック

トラックバックURL:

コメント

コメントを投稿する






Vodafone絵文字 i-mode絵文字 Ezweb絵文字 (絵文字)



<<PHP1-54:PHPでオンライン辞書 | HOME | PHP1-52:PHPでバグ管理>>
忍者ブログ[PR]