PHP双向地图

I'm porting to PHP a piece of Java code that uses a lot of Bi-directional maps (Guava's BiMap). Java-like maps are provided by PHP arrays or SplObjectStorage, but is there a library PHP Bi-Directional map available?

I did that once putting the values into 2 arrays. If keySet() and valueSet() are disjunct you can even use one value. Example:

$mapKtoV = array();
$mapVtoK = array();

function putInMap ($key,$value)
{
    $mapKtoV[$key] = $value;
    $mapVtoK[$value] = $key;
}

Of course you can also put them into a class.

Do you also think that this solution appears dodgy and smells? Yes, true, welcome to the world of PHP, which is usually dominated by bad code design. If you are really looking for a good solution, you should actually port you source from PHP to Java ;)

Hope it helps.

This class should provide for most needs of a bi-directional map :

class BiMap
{

    private $KtoV, $VtoK;

    public function __constructor()
    {
        $this->KtoV = []; // for version < 5.4.0, syntax must be: $this->KtoV = array();
        $this->VtoK = [];
    }

    public function getKey($v)
    {
        if($this->hasValue($v))
        {
            return $this->VtoK[$v];
        }
        else
        {
            return null;
        }
    }

    public function getAllKeys()
    {
        if($this->KtoV)
        {
            return array_keys($this->KtoV);
        }
        else
        {
            return $this->KtoV;
        }
    }

    public function getValue($k)
    {
        if($this->hasKey($k))
        {
            return $this->KtoV[$k];
        }
        else
        {
            return null;
        }
    }

    public function getAllValues()
    {
        if($this->VtoK)
        {
            return array_keys($this->VtoK);
        }
        else
        {
            return $this->VtoK;
        }
    }

    public function hasKey($k)
    {
        return isset($this->KtoV[$k]);
    }

    public function hasValue($v)
    {
        return isset($this->VtoK[$v]);
    }

    public function put($k, $v)
    {
        if($this->hasKey($k))
        {
            $this->removeKey($k);
        }
        if($this->hasValue($v))
        {
            $this->removeValue($v);
        }
        $this->KtoV[$k] = $v;
        $this->VtoK[$v] = $k;
    }

    public function putAll($array)
    {
        foreach($array as $k => $v)
        {
            $this->put($k, $v);
        }
    }

    public function removeKey($k)
    {
        if($this->hasKey($k))
        {
            unset($this->VtoK[$this->KtoV[$k]]);
            $v = $this->KtoV[$k];
            unset($this->KtoV[$k]);
            return $v;
        }
        else
        {
            return null;
        }
    }

    public function removeValue($v)
    {
        if($this->hasValue($v))
        {
            unset($this->KtoV[$this->VtoK[$v]]);
            $k = $this->VtoK[$v];
            unset($this->VtoK[$v]);
            return $k;
        }
        else
        {
            return null;
        }
    }

}

However, if you require null checking for key/values and/or object/array checking then handling similar to the following lines of code should be given in the body of a function and called appropriately within the hasKey($k), hasValue($v) and put($k, $v) methods :

    if($item === null)
    {
        throw new Exception('null as BiMap key / value is invalid.');
    }
    if(is_object($item) || is_array($item))
    {
        throw new Exception('Object / Array as BiMap key / value is invalid.');
    }