3

ラッパークラスを作成したいのですが、デフォルトのハッシュでは許可されていませんが、キーの複製が有効になります。クラスはphp5で導入されたメンバーのオーバーロードメカニズムを使用する必要があるため、標準ハッシュのすべての動作を模倣します。たとえば、私は次のようなsmthが欲しい

$var => obj( :values_arr -> array(
      obj(:key -> 'mykey', :value -> 'val1'), 
      obj(:key -> 'mykey', :value -> 'val2')
    )
)

$ var ['mykey']を取得する場合は、array('val1'、'val2')を返す必要がありますが、objを新しい'mykey' =>'value'ペアで拡張する場合は、

$val['mykey'][] = 'value'

主なアイデアは、ハッシュの動作が保持され、既存のキーの使用に値を割り当てようとした後、上書きされずにリストに追加されるというものです。

php5(5.3より前)の他のデータ構造をどのように模倣しますか?共有したい既知の解決策や例はありますか?

4

2 に答える 2

2

このような

class MultiMap
{
    protected $map = array();

    function __set($key, $val) {
        if(!isset($this->map[$key]))  
           return $this->map[$key] = $val;
        if(!is_array($this->map[$key]))
           $this->map[$key] = array($this->map[$key]);
        $this->map[$key][] = $val;
    }
    function __get($key) {
       return $this->map[$key];
    }
}

$m = new MultiMap;
$m->foo = 1;
$m->foo = 2;
$m->bar = 'zzz';
print_r($m->foo);
print_r($m->bar);

しかし、全体のアイデアは私には少し奇妙に見えます。なぜこれが必要なのか説明できますか?

なぜASTのキーとして演算子が必要なのか、私には明らかではありません。おそらく、このような構造の方が便利でしょう

   ('op' => 'AND', 'args' => [
        (op => AND, args => [
            (op  => atom, value => word1),
            (op  => atom, value => word2),
        ]),
        (op => AND, args => [
            (op  => atom, value => word3),
            (op  => atom, value => word4),
        ])
    ])
于 2009-11-25T13:50:48.880 に答える
0

配列構文を実現できます

$val['mykey'] = 'value';

ArrayAccessインターフェース付き

class MultiHash implements ArrayAccess, IteratorAggregate
{
    protected $data;

    public function offsetGet($offset)
    {
        return $this->data[$offset];
    }
    public function offsetSet($offset, $value)
    {
        if ($offset === null) { // $a[] = ...
            $this->data[] = array($value);
        } else {
            $this->data[$offset][] = $value;
        }
    }
    public function offsetExists($offset)
    {
        return isset($this->data[$offset]);
    }
    public function offsetUnset($offset)
    {
        unset($this->data[$offset]);
    }

    public function getIterator()
    {
        $it = new AppendIterator();
        foreach ($this->data as $key => $values) {
            $it->append(new ConstantKeyArrayIterator($values, 0, $key));
        }
        return $it;
    }
}

class ConstantKeyArrayIterator extends ArrayIterator
{
    protected $key;

    public function __construct($array = array(), $flags = 0, $key = 0)
    {
        parent::__construct($array,$flags);
        $this->key = $key;
    }
    public function key()
    {
        return parent::key() === null ? null : $this->key;
    }
}

IteratorAggregateまた、すべての単一要素で反復できるように実装しました。

テストコード

$test = new MultiHash();
$test[] = 'foo';
$test[] = 'bar';
$test['mykey'] = 'val1';
$test['mykey'] = 'val2';
$test['mykey2'] = 'val3';

echo "mykey: ";
var_dump($test['mykey']);

echo "mykey2: ";
var_dump($test['mykey2']);

echo "iterate:\n";
foreach ($test as $key => $value) {
    echo "$key : $value \n";
}

テスト出力

mykey: array(2) {
  [0]=>
  string(4) "val1"
  [1]=>
  string(4) "val2"
}
mykey2: array(1) {
  [0]=>
  string(4) "val3"
}
iterate:
0 : foo 
1 : bar 
mykey : val1 
mykey : val2 
mykey2 : val3 
于 2013-02-16T12:16:17.907 に答える