デフォルトのハッシュの代わりにPHPで重要な複製を使用してデータ構造を作成する方法は?

StackOverflow https://stackoverflow.com/questions/1796937

  •  22-09-2019
  •  | 
  •  

質問

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

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

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

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

主な考え方は、ハッシュの動作が保存され、既存のキーを使用することに値を割り当てようとすると、上書きされることはありませんが、リストに追加されるということです。

PHP5の他のデータ構造をどのように模倣しますか(5.3以前)?共有したい既知のソリューションや例はありますか?

役に立ちましたか?

解決

このような

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),
        ])
    ])

他のヒント

配列構文を実現できます

$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 
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top