2012-09-27 93 views
28

我正在尋找一個簡單的函數來將數組元素移動到數組中的新位置,並對索引進行重新排序,以便序列中沒有間隔。它不需要使用關聯數組。任何人都有這個想法嗎?將數組元素移動到PHP中的新索引中

$a = array(0=>'a', 1=>'c', 2=>'d', 3=>'b', 4=>'e'); 
print_r(moveElement(3,1)) 
//should output [0=>'a', 1=>'b', 2=>'c', 3=>'d', 4=>'e'] 
+5

請添加示例和預期的行爲..還有,你有什麼嘗試? –

+0

一些代碼與預期的結果將有助於... – Baba

+0

你在尋找'array_values'? – Gordon

回答

73

至於評論,2X array_splice,甚至有沒有必要重新編號:

$array = [0=>'a', 1=>'c', 2=>'d', 3=>'b', 4=>'e']; 

function moveElement(&$array, $a, $b) { 
    $out = array_splice($array, $a, 1); 
    array_splice($array, $b, 0, $out); 
} 

moveElement($array, 3, 1); 

結果:

[0=>'a', 1=>'b', 2=>'c', 3=>'d', 4=>'e']; 
+0

是的,它是很好很簡單的解決方案,但它只有在舊索引大於新索引時纔有效。這是另一個解決方案:[link](http://stackoverflow.com/questions/9212312/moving-up-down-an-item-in-the-array-by-its-value) – quarky

+2

@quarky:不,它如果新索引大於舊索引,也可以工作。如果兩者都是相同的。 – hakre

+4

但是,如果您的目的地是在源之後,它可能不會將它放在您預測的位置,因爲在第一步之後數組變短。如果移動到最後,你不想使用size-1,你想要size-2 –

1

我認爲您正在尋找內建函數usort。來自鏈接參考頁面的示例:

<?php 
function cmp($a, $b) 
{ 
    if ($a == $b) { 
     return 0; 
    } 
    return ($a < $b) ? -1 : 1; 
} 

$a = array(3, 2, 5, 6, 1); 

usort($a, "cmp"); 

foreach ($a as $key => $value) { 
    echo "$key: $value\n"; 
} 
?> 
+0

那麼,'usort'與你的回調和只是'sort()'有什麼區別?這又是如何解決這個問題的? – KingCrunch

+0

沒有什麼區別,它只是在那裏演示功能的用法。 – soulmerge

0

您需要創建一個輔助變量。

moveElement($a, $i,$j) 
    { 
    $k=$a[$i]; 
    $a[$i]=$a[$j]; 
    $a[$j]=$k; 
    return $a; 
    } 
+1

這更像是'swapElements()',但不會移動 – KingCrunch

+0

從他的例子看來,他正在嘗試...... –

+0

否:'c'將會轉到'3'而不是'2',就像這個例子。 – KingCrunch

0

看看this線程,它描述了類似的問題。下列溶液提供了:

/** 
* Move array element by index. Only works with zero-based, 
* contiguously-indexed arrays 
* 
* @param array $array 
* @param integer $from Use NULL when you want to move the last element 
* @param integer $to New index for moved element. Use NULL to push 
* 
* @throws Exception 
* 
* @return array Newly re-ordered array 
*/ 
function moveValueByIndex(array $array, $from=null, $to=null) 
{ 
    if (null === $from) 
    { 
    $from = count($array) - 1; 
    } 

    if (!isset($array[$from])) 
    { 
    throw new Exception("Offset $from does not exist"); 
    } 

    if (array_keys($array) != range(0, count($array) - 1)) 
    { 
    throw new Exception("Invalid array keys"); 
    } 

    $value = $array[$from]; 
    unset($array[$from]); 

    if (null === $to) 
    { 
    array_push($array, $value); 
    } else { 
    $tail = array_splice($array, $to); 
    array_push($array, $value); 
    $array = array_merge($array, $tail); 
    } 

    return $array; 
} 
2

陣列在PHP不是在C SENS但關聯數組實際的數組。 但是將值從索引移動到另一個的方式是直接向前,並且與C++中的值相同:

將值移動到臨時緩衝區,翻譯所有元素以粉碎來源位置,並在同一個目標位置釋放一個點。 將備份值放入目標位置。

function moveElement ($a , $i , $j) 
{ 
     $tmp = $a[$i]; 
     if ($i > $j) 
     { 
      for ($k = $i; $k > $j; $k--) { 
       $a[$k] = $a[$k-1]; 
      }   
     } 
     else 
     { 
      for ($k = $i; $k < $j; $k++) { 
       $a[$k] = $a[$k+1]; 
      } 
     } 
     $a[$j] = $tmp; 
     return $a; 
} 


$a = array(0, 1, 2, 3, 4, 5); 
print_r($a); 

$a = moveElement($a, 1, 4); 
echo ('1 -> 4'); 
print_r($a); 


$a = moveElement($a, 5, 0); 
echo ('5 -> 0'); 
print_r($a); 

輸出:

Array 
(
    [0] => 0 
    [1] => 1 
    [2] => 2 
    [3] => 3 
    [4] => 4 
    [5] => 5 
) 
1 -> 4Array 
(
    [0] => 0 
    [1] => 2 
    [2] => 3 
    [3] => 4 
    [4] => 1 
    [5] => 5 
) 
5 -> 0Array 
(
    [0] => 5 
    [1] => 0 
    [2] => 2 
    [3] => 3 
    [4] => 4 
    [5] => 1 
) 

你需要添加一些異常處理有一個完整的代碼。

0

,保留鍵A的功能:

function moveElementInArray($array, $toMove, $targetIndex) { 
    if (is_int($toMove)) { 
     $tmp = array_splice($array, $toMove, 1); 
     array_splice($array, $targetIndex, 0, $tmp); 
     $output = $array; 
    } 
    elseif (is_string($toMove)) { 
     $indexToMove = array_search($toMove, array_keys($array)); 
     $itemToMove = $array[$toMove]; 
     array_splice($array, $indexToMove, 1); 
     $i = 0; 
     $output = Array(); 
     foreach($array as $key => $item) { 
      if ($i == $targetIndex) { 
       $output[$toMove] = $itemToMove; 
      } 
      $output[$key] = $item; 
      $i++; 
     } 
    } 
    return $output; 
} 

$arr1 = Array('a', 'b', 'c', 'd', 'e'); 
$arr2 = Array('A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e'); 

print_r(moveElementInArray($arr1, 3, 1)); 
print_r(moveElementInArray($arr2, 'D', 1)); 

輸出繼電器:

Array 
(
    [0] => a 
    [1] => d 
    [2] => b 
    [3] => c 
    [4] => e 
) 
Array 
(
    [A] => a 
    [D] => d 
    [B] => b 
    [C] => c 
    [E] => e 
) 
6

從hakre該溶液具有兩個array_splice命令不與命名的數組。被移動元素的關鍵字將會丟失。

相反,您可以拼接陣列兩次併合並這些部分。

function moveElement(&$array, $a, $b) { 
    $p1 = array_splice($array, $a, 1); 
    $p2 = array_splice($array, 0, $b); 
    $array = array_merge($p2,$p1,$array); 
} 

它是如何工作:

  • 一:刪除/從陣列拼接元素
  • 二:數組拼接成兩個部分的位置,你要插入的元素
  • 合併三個部分一起

實施例:

$fruits = array(
    'bananas'=>'12', 
    'apples'=>'23', 
    'tomatoes'=>'21', 
    'nuts'=>'22', 
    'foo'=>'a', 
    'bar'=>'b' 
); 

moveElement($fruits, 1, 3); 

// Result 
['bananas'=>'12', 'tomatoes'=>'21', 'nuts'=>'22', 'apples'=>'23', 'foo'=>'a', 'bar'=>'b'] 
+0

蘋果是索引1和番茄索引3.在您的結果番茄現在是1和蘋果現在索引4,而是堅果是索引3.那麼這個解決方案究竟是如何呢? – 2017-05-22 00:40:07

+0

你必須從0開始計數。蘋果在位置1,它被移動到位置3 – RubbelDeCatc

+0

你換了1,3。 **之前:(1 =蘋果,3 =堅果),你得到後**:1 =西紅柿3 =蘋果。這不是交換,它只是將蘋果移動到正確的索引(3),而不是堅果爲1,現在西紅柿爲1。 – 2017-05-24 14:37:38

1

可能是我錯了,但不應該是更容易只是做一個數組的副本,然後替換值?

function swap($input, $a, $b){ 
    $output = $input; 
    $output[$a] = $input[$b]; 
    $output[$b] = $input[$a]; 
    return $output; 
} 

$array = ['a', 'c', 'b']; 
$array = swap($array, 1, 2); 
+0

這樣你只交換兩個元素但是任務是移動 – RubbelDeCatc