Wie erstelle ich Datenstruktur mit Schlüssel Duplikaten in PHP anstelle von Standard -Hash?

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

  •  22-09-2019
  •  | 
  •  

Frage

Ich möchte eine Wrapper -Klasse erstellen, die Schlüssel Duplikate ermöglicht, während Standard -Hash dies nicht zulässt. Die Klasse sollte den in PHP5 eingeführten Mitglieder -Überladungsmechanismus verwenden, sodass er den gesamten Verhaltensstandard -Hash imitieren würde. Zum Beispiel möchte ich SMTH haben wie

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

Wenn ich $ var ['mykey'] bekommen möchte, sollte es Array ('Val1', 'Val2') zurückgeben, aber wenn ich OBJ mit neuem 'Mykey' => 'Value' -Paar erweitern möchte, würde ich anrufen

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

Die Hauptidee ist, dass das Verhalten des Hashs erhalten bleibt und nach dem Versuch, den Verwendung bestehender Schlüssel einen Wert zuzuweisen, wird es nicht überschrieben, sondern an die Liste angehängt.

Wie würden Sie andere Datenstrukturen in PHP5 (vor 5.3) nachahmen? Gibt es bekannte Lösungen oder Beispiele, die Sie teilen möchten?

War es hilfreich?

Lösung

so was

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);

Aber die ganze Idee sieht für mich ein bisschen seltsam aus. Können Sie erklären, warum Sie das brauchen?

Für mich ist nicht klar

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

Andere Tipps

Sie können die Array -Syntax erreichen

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

mit dem ArrayAccess Schnittstelle

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;
    }
}

Ich habe auch implementiert IteratorAggregate Iteration über alle einzelnen Elemente zu ermöglichen.

Testcode

$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";
}

Testausgabe

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 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top