3 回答

TA貢獻1809條經驗 獲得超8個贊
看起來你想要的東西很難用 PHP 的排序方法之一實現。此外,由于不匹配鍵的相對順序不應該改變,我們可以爭取比 O (nlogn)排序方法更好的時間復雜度。
因此,我建議編寫一個函數,對兩個數組 ( $array, $order) 進行一些迭代,以便按預期順序收集鍵/值對。這構成了O(n+m)時間復雜度,其中n和m是兩個數組的兩個大小。
這是功能:
function sortadjacent($array, $order) {
$insertAt = 0;
foreach($array as $key => $_) {
if (isset($order[$key])) break;
$insertAt++;
}
$special = [];
foreach($order as $key => $_) {
if (isset($array[$key])) $special[$key] = $array[$key];
}
$result = [];
foreach($array as $key => $value) {
if (!isset($order[$key])) $result[$key] = $value;
else if (count($result) == $insertAt) $result = array_merge($result, $special);
}
return $result;
}
你會這樣稱呼它:
$result = sortadjacent($array, $order);
請注意,此函數不會對 進行更改$array,而是在新數組中返回預期結果。

TA貢獻1829條經驗 獲得超13個贊
您的實現非常接近,但是您必須在比較函數中考慮這種情況,其中只有一個您想要的鍵存在,而其他任何鍵都不存在。如果你return 0在那種情況下,它們將在你的數組中的其他鍵中被破壞(因為它們在這種情況下的位置被認為是相等的)。
由于您還希望保留現有鍵的序列,并在之后插入其他“提取的”鍵country_id,因此您可以保留對原始排序順序的引用,并使用它來解析與country_id其他字段相關的排序順序(和其他字段之間以保持當前排序順序)
通過處理這兩種特殊情況以明確地對您希望自己依次出現的鍵進行排序,您將獲得滿足您要求的結果:
$order = ['country_id' => 1, 'region' => 2, 'region_id' => 3, 'city' => 4, 'city_id' => 5];
$preset_order = array_flip(array_keys($array));
uksort($array, function ($a, $b) use ($order, $preset_order) {
if (isset($order[$a]) && isset($order[$b])) {
return $order[$a] - $order[$b];
} else if (isset($order[$a])) {
return $preset_order['country_id'] - $preset_order[$b];
} else if (isset($order[$b])) {
return $preset_order[$a] - $preset_order['country_id'];
} else {
return $preset_order[$a] - $preset_order[$b];
}
});
輸出:
array(8) {
'name' =>
array(1) {
'value' =>
string(6) "Raj KB"
}
'street' =>
array(1) {
'value' =>
string(10) "Street ABC"
}
'country_id' =>
array(1) {
'value' =>
string(3) "UAE"
}
'region' =>
array(1) {
'value' =>
string(3) "DXB"
}
'region_id' =>
array(1) {
'value' =>
int(11)
}
'city' =>
array(1) {
'value' =>
string(5) "Dubai"
}
'city_id' =>
array(1) {
'value' =>
int(22)
}
'zip_code' =>
array(1) {
'value' =>
int(12345)
}
}

TA貢獻1862條經驗 獲得超6個贊
PHP 使用Quicksort,因此您不能只為要排序的元素返回有意義的值。在我看來,在這里使用 uksort 是個壞主意,因為您必須使用數組的當前索引作為值,但這是不可能的,因為您無法從比較函數內部訪問舊數組的副本。您還需要知道第一個特殊值在哪個索引上。
所以我建議這樣做,因為我認為用 uksort 做你想做的事是不可能的:
function customSort($array)
{
$order = ['country_id' => 0, 'region' => 1, 'region_id' => 2, 'city' => 3, 'city_id' => 4];
$keyArray = array();
$sortedArray = array();
foreach ($array as $i => $value) {
$keyArray[] = $i;
}
$counter = 0;
$hasStarted = false;
$insertLater = array();
for ($i = 0; $i < count($keyArray); $i++) {
if ($hasStarted) {
if ($counter < count($order)) {
$sortedArray[array_search($counter, $order)] = $array[array_search($counter, $order)];
$counter++;
if (!isset($order[$keyArray[$i]])) {
array_push($insertLater, ["key" => $keyArray[$i], "value" => $array[$keyArray[$i]]]);
}
continue;
}
}
if (count($insertLater) > 0) {
$itemToInsert = array_shift($insertLater);
$sortedArray[$itemToInsert["key"]] = $itemToInsert["value"];
if (!isset($order[$keyArray[$i]])) {
array_push($insertLater, ["key" => $keyArray[$i], "value" => $array[$keyArray[$i]]]);
}
continue;
}
if (isset($order[$keyArray[$i]]) && !$hasStarted) {
$sortedArray[array_search($counter, $order)] = $array[array_search($counter, $order)];
$hasStarted = true;
$counter++;
continue;
}
$sortedArray[$keyArray[$i]] = $array[$keyArray[$i]];
}
return $sortedArray;
}
It's may
不是最好的解決方案,但它有效 O(n)。
- 3 回答
- 0 關注
- 191 瀏覽
添加回答
舉報