我已经尝试了很长一段时间,包括array_combine()
,array_keys()
,array_values()
等各种解决方案,但我的解决方案都没有结束工作正常。
基本上说我们有一个特定顺序的关联数组,而我试图改变它的位置 - 无论是相对还是绝对的方式,它都没有&#39无所谓此代码演示了我的错误,低效的版本:
<?php
$testArray = [
'a' => 'Item 1',
'b' => 'Item 2',
'c' => 'Item 3',
'd' => 'Item 4',
'e' => 'Item 5',
'f' => 'Item 6',
'g' => 'Item 7',
'h' => 'Item 8',
'i' => 'Item 9',
];
function moveKey($array, $key, $position) {
// Now the array will have [position] => key
$arrayKeyPos = array_keys($array);
// This is so we can have duplicate positions and not overwrite one another
// We're now [key] => position
$arrayKeyPos = array_flip($arrayKeyPos);
// Now this should change the key's position
$arrayKeyPos[$key] = $position;
// Sort them
asort($arrayKeyPos, SORT_NUMERIC);
// At this point the array's keys are in correct order. But there
// is no easy way to attach the values? This is pretty ugly:
$newArray = [];
foreach($arrayKeyPos as $k => $v) {
$newArray[$k] = $array[$k];
}
return $newArray;
}
$testArray = moveKey($testArray, 'c', 99);
// This "sort of" works, it moves it to the 4th, not 3rd, position:
$testArray = moveKey($testArray, 'h', 3);
所以要清楚,我的问题是如何完成上述操作,但是第二次调用总是将它移动到第N个位置?
显然,如果索引超出范围(小于此数组的-99,99等),它应该只是转到顶部/底部,但对于那些诸如&#39; 3&#39;,&# 39; 5&#39;等等这段代码惨遭失败。
答案 0 :(得分:2)
如果$key
大于数组中的最后一个位置,则将$position
指定的元素移动到数组的末尾,如果小于1,则将其移动到开头:
function moveKey($array, $key, $position) {
$keys = array_keys($array);
$vals = array_values($array);
$pos = array_search($key, $keys);
$new_key = array_splice($keys, $pos, 1);
$new_val = array_splice($vals, $pos, 1);
array_splice($keys, $position-1, 0, $new_key);
array_splice($vals, $position-1, 0, $new_val);
return array_combine($keys, $vals);
}
要在$position
超出范围时返回数组:
function moveKey($array, $key, $position, $wrap=true) {
if($wrap === false && ($position < 1 || $position > count($array)) {
return $array;
}
// rest of code
}
答案 1 :(得分:2)
您可以使用unset
从原始位置移除键/值,并将slice
与+
结合使用,将该对插入所需的绝对位置:
function moveKey($array, $key, $position) {
$value = $array[$key];
unset($array[$key]);
return array_slice($array, 0, $position, true) +
[$key => $value] +
array_slice($array, $position, null, true);
}
给定的位置被解释为从零开始,所以如下:
var_export (moveKey($testArray, "h", 3));
将返回:
array (
'a' => 'Item 1',
'b' => 'Item 2',
'c' => 'Item 3',
'h' => 'Item 8',
'd' => 'Item 4',
'e' => 'Item 5',
'f' => 'Item 6',
'g' => 'Item 7',
'i' => 'Item 9',
)
如果position参数大于最高索引,则键/值对将以数组的最后位置结束。
如果position参数为负,则位置从数组末尾开始向后计数。如果它导致数组开始之前的位置,则该对将在返回的数组的开头处结束。
在PHP中,索引数组是从零开始的。例如,如果您使用array_values($array)
,则第一个元素将具有索引0
。或者,如果您创建类似[1, 2, 3]
的索引数组,则值1
将位于索引0
。因此,如果您要混合使用基于1和0的索引号,您将会遇到很多-1
和+1
代码,这些代码最终会比很有帮助。我强烈建议适应基于0的索引号。
在PHP中,有几个函数提供了这个特性,即位置的负参数被解释为从数组末尾开始的向后偏移。例如array_splice
:
如果偏移为正,则移除部分的开始位于距输入数组开头的偏移处。如果offset是负数,那么它将从输入数组的末尾开始。
array_slice
以及strpos
和strspn
等多个字符串函数也是如此。对explode
的极限参数实施了类似的负值处理。
因此,我认为坚持这种行为并将其视为一项功能会更好。当然,正如评论中所提到的,很容易禁用此功能,并使用0
将任何负偏移转换为if ($position < 0) $position = 0;
。