Come creare una struttura dati con duplicati di chiave in php invece dell'hash predefinito?

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

  •  22-09-2019
  •  | 
  •  

Domanda

Voglio creare una classe wrapper, che abiliterà i duplicati delle chiavi mentre l'hash predefinito non lo consente.La classe dovrebbe utilizzare il meccanismo di sovraccarico dei membri introdotto in php5, quindi imiterebbe tutto il comportamento dell'hash standard.Ad esempio, voglio avere qualcosa di simile

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

Se voglio ottenere $var['mykey'], dovrebbe restituire array('val1', 'val2'), ma se voglio estendere obj con la nuova coppia 'mykey' => 'value', chiamerei

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

L'idea principale è che il comportamento dell'hash venga preservato e, dopo il tentativo di assegnare un valore utilizzando la chiave esistente, non verrebbe sovrascritto, ma aggiunto all'elenco.

Come imiteresti altre strutture dati in php5 (prima della 5.3)?Ci sono soluzioni conosciute o esempi che vuoi condividere?

È stato utile?

Soluzione

come questo

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

, ma l'idea sembra un po 'strano per me. Può spiegare perché avete bisogno di questo?

non è chiaro per me perché hai bisogno di operatori come chiavi nel vostro AST forse una struttura come questa sarebbe più conveniente

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

Altri suggerimenti

È possibile ottenere la sintassi dell'array

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

con il ArrayAccess interfaccia

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

Ho anche implementato IteratorAggregate per consentire l'iterazione su tutti i singoli elementi.

Codice di prova

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

Prova uscita

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 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top