Friday, May 16, 2008

Multiple Key Array in PHP

Sometimes there is need for use of multiple key array in PHP, in order to get more speed. This drawbacks the use of memory, but this is desirable in some situations.

Let's assume you have some database small tables with some information (let's say categories, or sections) that is needed to be retrieved multiple times at the runtime, in the same script. This consumes a lot of time. What if we retrieve it once and cache it in memory? But how do we access the data based on some keys?

One idea is to put the rows into array and make a search functions that searches by iteration on the array by a field name and it's value, in order to retrieve only needed row. This will consume some processing time, also, the algorithm is O(n), averages n/2 iterations.

Another idea is to have a multiple keys array. This will give better access (depending on way PHP retrieve the data from arrays based on one key). The code for this implementation it's below:


class MultiKeyArray {
private $elements = array();

private $refcnts = array();

private $keys = array();

public function __construct() {

} // end construct

public function add($key, $arr) {
if (!array_key_exists($key, $arr))
return FALSE;

$val = $arr[$key];

$skey = array_search($arr, $this->elements);
if ($skey === FALSE) {
$this->elements[] = $arr;

$_dropval = end($this->elements);
$lastKey = key($this->elements);

$this->refcnts[$lastKey] = 1;
}
else {
$this->refcnts[$skey]++;
$lastKey = $skey;
}

$this->keys["$key"]["$val"] = $lastKey;

return TRUE;
}

public function remove($key, $arr) {
if (!array_key_exists($key, $arr))
return FALSE;

$val = $arr[$key];

unset($this->keys["$key"]["$val"]);
if (!count($this->keys["$key"]))
unset ($this->keys["$key"]);

$key = array_search($arr, $this->elements);
if($this->refcnts[$key] > 1)
$this->refcnts[$key]--;
else {
unset($this->elements[$key]);
unset($this->refcnts[$key]);
}

return TRUE;
}

public function get($key, $keyVal) {
if (!array_key_exists("$key", $this->keys) || !array_key_exists("$keyVal", $this->keys["$key"]))
return NULL;

$elemKey = $this->keys["$key"]["$keyVal"];
return $this->elements[$elemKey];
}
} /* end class MultiKeyArray */



// sample usage

$v = array(
"id" => 1,
"code" => "00",
"alias" => "main",
"name" => "Acasă",
);

$v2 = array(
"id" => 2,
"code" => "01",
"alias" => "stiri",
"name" => "Ştiri",
);

$a = new MultiKeyArray();

$a->add("id", $v);
$a->add("code", $v);

$a->add("id", $v2);

$b = $a->get("id", "2");

var_dump($b);

$a->remove("id", $v);
$a->remove("code", $v);
$a->remove("id", $v2);


Certainly, this can be used in other kind of applications where we need to retrieve the same array data based on multiple indexes.