A two array data structure implementation in PHP, version 1
In this version of two dimentional array data structure implementation in PHP, we use the simple approach without using any more advanced PHP features (like iterators). Because of the step-by-step attitude of these articles (the next versions, I mean), We try to use some compatible codes along with all versions.
The final desired result is a class called IntTwoDimArray
(as well as FloatTwoDimArray
and etc.) that used by initialization statement $intMatrix = new IntTwoDimArray($size);
, and later used by setter and getters like this:
echo $intMatrix->Set($i, $j, $v)
echo $intMatrix->Get($i, $j)
At the first, we create a simple abstract class called AbstractTwoDimArray
.
The very first thing we learn about simple arrays is that there is a limitation for the number of items. (changeable in case of the dynamic array and fixed in case of fixed or static arrays) We tend to implement a simple array, and by simple we mean fixed size as well.
protected $_size = [0, 0];
We use the native PHP array as a data holder for own data structure. (As it seems rediculous, but we focus on teaching purposes)
protected $_values = [];
To acess the array size, we implement a Size
method.
public function Size() : array
{
return $this->_size;
}
Until now, the implemented class seems like this:
abstract class AbstractTwoDimArray
{
protected $_size = [0, 0];
protected $_values = [];
public function __construct(int $rows, int $cols)
{
if ($rows _size = [$rows, $cols];
$defaultValue = $this->getDefaultValue();
if (gettype($defaultValue) != $this->getValueType())
throw new Exception('Return type of the getDefaultValue() does not match getValueType().');
for ($row = 0; $row _size[0]; $row++) {
for ($col = 0; $col _size[1]; $col++)
$this->_values[$row][$col] = $defaultValue;
}
}
public function Size() : array
{
return $this->_size;
}
}
For the reason that out abstract class must be a parent class for concrete classes, and each concrete class has it's own data type, we declare an abstract method called getValueType
to be implemented in each concrete class.
protected abstract function getValueType() : string;
Also, we declare another abstract method to return default value for the specified data type.
protected abstract function getDefaultValue();
We use this methods in the constructor like this:
public function __construct(int $rows, int $cols)
{
if ($rows _size = [$rows, $cols];
$defaultValue = $this->getDefaultValue();
if (gettype($defaultValue) != $this->getValueType())
throw new Exception('Return type of the getDefaultValue() does not match getValueType().');
for ($row = 0; $row _size[0]; $row++) {
for ($col = 0; $col _size[1]; $col++)
$this->_values[$row][$col] = $defaultValue;
}
}
Of course, it must contain getter and setter methods to be an array data structure parent class! The implementation is like this:
public function Set(int $row, int $col, $value)
{
if ($row = $this->_size[0])
throw new Exception('The row index must be in the range (0, ' . ($this->_size[0] -1) . ')');
if ($col = $this->_size[1])
throw new Exception('The col index must be in the range (0, ' . ($this->_size[1] -1) . ')');
if (gettype($value) != $this->getValueType())
throw new Exception('The value must be of type ' . $this->getValueType());
$this->_values[$row][$col] = $value;
}
public function Get(int $row, int $col)
{
if ($row = $this->_size[0])
throw new Exception('The row index must be in the range (0, ' . ($this->_size[0] -1) . ')');
if ($col = $this->_size[1])
throw new Exception('The col index must be in the range (0, ' . ($this->_size[1] -1) . ')');
return $this->_values[$row][$col];
}
The base class is finished now and it's like this:
abstract class AbstractTwoDimArray
{
/**
*
* @var array
*/
private /*array*/ $_size = [0, 0];
/**
*
* @var array
*/
private /*array*/ $_values = [];
protected abstract function getValueType() : string;
protected abstract function getDefaultValue();
public function __construct(int $rows, int $cols)
{
if ($rows _size = [$rows, $cols];
$defaultValue = $this->getDefaultValue();
if (gettype($defaultValue) != $this->getValueType())
throw new Exception('Return type of the getDefaultValue() does not match getValueType().');
for ($row = 0; $row _size[0]; $row++) {
for ($col = 0; $col _size[1]; $col++)
$this->_values[$row][$col] = $defaultValue;
}
}
public function Size(): array
{
return $this->_size;
}
public function Set(int $row, int $col, $value)
{
if ($row = $this->_size[0])
throw new Exception('The row index must be in the range (0, ' . ($this->_size[0] -1) . ')');
if ($col = $this->_size[1])
throw new Exception('The col index must be in the range (0, ' . ($this->_size[1] -1) . ')');
if (gettype($value) != $this->getValueType())
throw new Exception('The value must be of type ' . $this->getValueType());
$this->_values[$row][$col] = $value;
}
public function Get(int $row, int $col)
{
if ($row = $this->_size[0])
throw new Exception('The row index must be in the range (0, ' . ($this->_size[0] -1) . ')');
if ($col = $this->_size[1])
throw new Exception('The col index must be in the range (0, ' . ($this->_size[1] -1) . ')');
return $this->_values[$row][$col];
}
}
Now to use this base class, we need to derive a concrete class. For example we make the class IntTwoDimArray
to use as an integral array.
class IntTwoDimArray extends AbstractTwoDimArray
{
protected function getValueType() : string
{
return gettype(0);
}
protected function getDefaultValue()
{
return 0;
}
}
As you see, We only need to implement the two methods getValueType
and getDefaultValue
. The other operations is derived from the base class. Lets test implemented code with an execution.
$rows = 5;
$cols = 5;
$intMatrix = new IntTwoDimArray($rows, $cols);
for ($row = 0; $row Size()[0]; $row++) {
for ($col = 0; $col Size()[1]; $col++)
echo $intMatrix->Get($row, $col) . ' ';
echo PHP_EOL;
}
echo PHP_EOL;
for ($row = 0; $row Size()[0]; $row++) {
for ($col = 0; $col Size()[1]; $col++)
$intMatrix->Set($row, $col, $row + $col);
}
for ($row = 0; $row Size()[0]; $row++) {
for ($col = 0; $col Size()[1]; $col++)
echo $intMatrix->Get($row, $col) . ' ';
echo PHP_EOL;
}
echo PHP_EOL;
Code
<?php
namespace Techanic\CS\DS\Linear\Vector;
use Exception;
abstract class AbstractTwoDimArray
{
/**
*
* @var array
*/
private /*array*/ $_size = [0, 0];
/**
*
* @var array
*/
private /*array*/ $_values = [];
protected abstract function getValueType() : string;
protected abstract function getDefaultValue();
public function __construct(int $rows, int $cols)
{
if ($rows < 0)
throw new Exception('rows must be positive number.');
if ($cols < 0)
throw new Exception('cols must be positive number.');
$this->_size = [$rows, $cols];
$defaultValue = $this->getDefaultValue();
if (gettype($defaultValue) != $this->getValueType())
throw new Exception('Return type of the getDefaultValue() does not match getValueType().');
for ($row = 0; $row < $this->_size[0]; $row++) {
for ($col = 0; $col < $this->_size[1]; $col++)
$this->_values[$row][$col] = $defaultValue;
}
}
public function Size(): array
{
return $this->_size;
}
public function Set(int $row, int $col, $value)
{
if ($row < 0 || $row >= $this->_size[0])
throw new Exception('The row index must be in the range (0, ' . ($this->_size[0] -1) . ')');
if ($col < 0 || $col >= $this->_size[1])
throw new Exception('The col index must be in the range (0, ' . ($this->_size[1] -1) . ')');
if (gettype($value) != $this->getValueType())
throw new Exception('The value must be of type ' . $this->getValueType());
$this->_values[$row][$col] = $value;
}
public function Get(int $row, int $col)
{
if ($row < 0 || $row >= $this->_size[0])
throw new Exception('The row index must be in the range (0, ' . ($this->_size[0] -1) . ')');
if ($col < 0 || $col >= $this->_size[1])
throw new Exception('The col index must be in the range (0, ' . ($this->_size[1] -1) . ')');
return $this->_values[$row][$col];
}
}
class IntTwoDimArray extends AbstractTwoDimArray
{
protected function getValueType() : string
{
return gettype(0);
}
protected function getDefaultValue()
{
return 0;
}
}
$rows = 5;
$cols = 5;
$intMatrix = new IntTwoDimArray($rows, $cols);
for ($row = 0; $row < $intMatrix->Size()[0]; $row++) {
for ($col = 0; $col < $intMatrix->Size()[1]; $col++)
echo $intMatrix->Get($row, $col) . ' ';
echo PHP_EOL;
}
echo PHP_EOL;
for ($row = 0; $row < $intMatrix->Size()[0]; $row++) {
for ($col = 0; $col < $intMatrix->Size()[1]; $col++)
$intMatrix->Set($row, $col, $row + $col);
}
for ($row = 0; $row < $intMatrix->Size()[0]; $row++) {
for ($col = 0; $col < $intMatrix->Size()[1]; $col++)
echo $intMatrix->Get($row, $col) . ' ';
echo PHP_EOL;
}
echo PHP_EOL;