-1

我尝试使用array_splice此处描述的策略 ​​在 PHP 中的任何位置插入数组中的新项目

但它不起作用,因为数组为空或键不存在。所以我尝试检查是否先设置密钥然后创建它。但它仍然不起作用。

例如,如果数组在第一次调用中为空,并且我想在索引 3 处插入元素,并且array_splicearray_splice. 如果数组为空,则插入失败

function array_insert($array,$input,$index){
    if(!isset($array[$index])) $array[$index] = 0;
    array_splice($array,$index,0,$input);

    return $array;
}

所以下面的调用

array_insert(array(),array(36,37),3);

生成这个

array(1) { [3]=> int(0) } //var_dump before splice, after isset
array(3) { [0]=> int(0) [1]=> string(2) "36" [2]=> string(2) "37" } //var_dump  after splice

我错过了什么?!

@edit 预期的结果是:如果我在空数组的第 3 位插入数组('a','b','c'),则结果数组应该允许我通过键 3,'b' 访问 'a'由 4 等。不确定哪个更好,空值来填补空白或关联键。

@edit2

insert(array(),array(1,2),3);

数组(2) { [3]=> int(1) [4]=> int(2) }

$a = array(); $a[2] = 3; insert($a,array(1,2),1);

数组(3) { 1 => int(1) [2]=> int(2) [3] => int(3) }

insert(array(1,2),array(4,5),1);

数组(4) { [0]=> int(1) 1 => int(4) [2] => int(5) [3] => int(2) }

在性能方面,顺便说一句更好的选择是什么?

4

3 回答 3

2

我认为这可以满足您的要求,并且我已经包含了测试用例,因此您可以自己判断。

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";
于 2015-06-10T00:34:06.983 回答
1

一段时间后,我和一个朋友设法使它工作。相信对很多人都有用

function array_max_key($a){
  if(count($a)) return max(array_keys($a));
  return 0;
}

function array_insert($a,$b,$index){
  if(!is_array($b)) $b = array($b);

  $max = array_max_key($a);
  if($index > $max) $max = $index;
  $ab = array();
  $max++;

  for($i=0;$i<$max;$i++){
    if(isset($a[$i]) && $i<$index){
        $ab[$i] = $a[$i];
    }else if($i == $index){
        $_max = count($b);
        for($j=0;$j<$_max;$j++){
            $ab[$i+$j] = $b[$j];
        }
        if(isset($a[$i])) $ab[] = $a[$i];
    }else if(isset($a[$i])){
        if(isset($ab[$i])) $ab[] = $a[$i];
        else $ab[$i] = $a[$i];
    }
  }

  return $ab;
}

 array_insert(array(),array(1,2,3),4);
 $a = array(); $a[5] = 1; $a[6] = 2;
 array_insert($a,2,4);

因此,如果您尝试将元素添加到数组的 I 位置,即使该位置不存在(或数组为空),它也会添加它们,并在发现冲突时移动其他元素。元素可以是数组,也可以不是

于 2015-06-09T22:11:50.373 回答
0

你谈了很多拼接,所以我决定不写我的变种。但这不是绝对的:)

function array_insert($array, $add, $index) {
  // make array with desired keys
  $add = array_combine(range($index, $index + count($add)-1), $add);
  // split old array to two parts - (0 <= key < $index) and ($index <= key) 
  $after = $index ? array_diff_key($array, array_flip(range(0, $index-1))) : $array;
  $before = array_diff($array, $after);
  // Combine arrays
  $array = array_replace($add, $before);
  foreach($after as $item)
     $array[] = $item;
   return($array);    
}

print_r(array_insert(array(), array(a,b,c), 3));
// Array ( [3] => a [4] => b [5] => c )
print_r(array_insert(range(1,10), array(a,b,c), 3));
// Array ( [3] => a [4] => b [5] => c [0] => 1 [1] => 2 [2] => 3 [6] => 4 [7] => 5 [8] => 6 [9] => 7 [10] => 8 [11] => 9 [12] => 10 )
print_r(array_insert(range(1,2), array(a,b,c), 3));
// Array ( [3] => a [4] => b [5] => c [0] => 1 [1] => 2 )
print_r(array_insert(array(10=>10,3=>3), array(a,b,c), 3));
// Array ([3] => a [4] => b [5] => c [6] => 10 [7] => 3 )
于 2015-06-09T23:36:19.913 回答