我认为这可以满足您的要求,并且我已经包含了测试用例,因此您可以自己判断。
class ShiftingArray implements ArrayAccess
{
private $values;
public function __construct ($initial_values = array ())
{
$this->values = $initial_values;
}
public function get_values ()
{
return $this->values;
}
public function insert ($new_values, $offset)
{
if (!is_array ($new_values))
{
$new_values = array ($new_values);
}
foreach ($new_values as $value)
{
$this->insert_single ($offset, $value);
$offset++;
}
}
private function insert_single ($index, $value)
{
if (isset ($this->values[$index]))
{
$this->insert_single ($index + 1, $this->values[$index]);
}
$this->values[$index] = $value;
}
/**
* The following methods allow you to use an instance of ShiftingArray
* like a normal array, e.g.
*
* $array = new ShiftingArray ();
* $array->insert (array (1,2,3), 4);
* echo $array[5]; // prints 2
*/
/* boolean ArrayAccess::offsetExists (mixed $offset) */
public function offsetExists ($offset)
{
return isset ($this->values [$offset]);
}
/* mixed ArrayAccess::offsetGet (mixed $offset) */
public function offsetGet ($offset)
{
return isset ($this->values [$offset]) ? $this->values[$offset] : null;
}
/* ArrayAccess::offsetSet (mixed $offset, mixed $value) */
public function offsetSet ($offset, $value)
{
$this->insert_single ($offset, $value);
}
/* ArrayAccess::offsetUnset (mixed $offset) */
public function offsetUnset ($offset)
{
unset ($this->values[$offset]);
}
}
// begin test cases
$test_cases = array (
array (
'Name' => 'Start Empty, Zero Offset, Single Insert',
'Initial' => array (),
'Insert' => 6,
'Offset' => 0,
'Output' => array (0 => 6),
),
array (
'Name' => 'Start Empty, Zero Offset',
'Initial' => array (),
'Insert' => array (3, 2),
'Offset' => 0,
'Output' => array (0 => 3, 1 => 2),
),
array (
'Name' => 'Start Empty, Positive Offset, Single Insert',
'Initial' => array (),
'Insert' => 'hello',
'Offset' => 11,
'Output' => array (11 => 'hello'),
),
array (
'Name' => 'Start Empty, Positive Offset',
'Initial' => array (),
'Insert' => array (9, 'blah'),
'Offset' => 3,
'Output' => array (3 => 9, 4 => 'blah'),
),
array (
'Name' => 'No Shift',
'Initial' => array (1 => 9),
'Insert' => array (4, 'blah'),
'Offset' => 3,
'Output' => array (1 => 9, 3 => 4, 4 => 'blah'),
),
array (
'Name' => 'Single Shift',
'Initial' => array (2 => 13),
'Insert' => 6,
'Offset' => 2,
'Output' => array (2 => 6, 3 => 13),
),
array (
'Name' => 'Single Element, Double Shift',
'Initial' => array (2 => 13),
'Insert' => array (6, 7),
'Offset' => 2,
'Output' => array (2 => 6, 3 => 7, 4 => 13),
),
array (
'Name' => 'Multiple Element, Double Shift',
'Initial' => array (5 => 13, 6 => 15),
'Insert' => array (2, 3),
'Offset' => 5,
'Output' => array (5 => 2, 6 => 3, 7 => 13, 8 => 15),
),
array (
'Name' => 'Shift Only Some',
'Initial' => array (2 => 1, 5 => 13, 6 => 15),
'Insert' => array (2, 3),
'Offset' => 5,
'Output' => array (2 => 1, 5 => 2, 6 => 3, 7 => 13, 8 => 15),
),
array (
'Name' => 'Shift Fills Gaps',
'Initial' => array (2 => 0, 3 => 11, 6 => 9, 7 => 'a'),
'Insert' => array (12, 14),
'Offset' => 4,
'Output' => array (2 => 0, 3 => 11, 4 => 12, 5 => 14, 6 => 9, 7 => 'a'),
),
);
// run tests
$passes = $failures = 0;
foreach ($test_cases as $case)
{
$array = new ShiftingArray ($case['Initial']);
$array->insert ($case['Insert'], $case['Offset']);
if ($array->get_values () != $case['Output'])
{
echo $case['Name'] . " FAILED\n";
print_r ($array->get_values ());
print_r ($case['Output']);
echo "\n\n";
$failures++;
}
else
{
$passes++;
}
}
echo "\n\nTests Finished: $passes Passes, $failures Failures";