【问题标题】:PHP: re order associative arrayPHP:重新排序关联数组
【发布时间】:2012-07-01 14:03:35
【问题描述】:

在 php 中,我希望能够通过将元素移动到数组中的某些位置来重新排序关联数组。不需要排序,只是我选择的重新排序。

例如,假设我有一个关联数组,如下所示:

array(
 'a' => 'Element A',
 'b' => 'Element B',
 'c' => 'Element C',
);

在一种情况下,我可能想将 C 移到 B 之前并得到以下结果:

array(
 'a' => 'Element A',
 'c' => 'Element C',
 'b' => 'Element B',
);

或者在另一种情况下,我可能想在 A 之前移动 C 并得到以下结果:

array(
 'c' => 'Element C',
 'a' => 'Element A',
 'b' => 'Element B',
);

我想展示的只是一种说“嘿,我想把这个数组元素移动到另一个数组元素之前”或“嘿,我想移动这个数组元素以确保它在后面”的方法这另一个数组元素'

希望这是有道理的!

提前感谢任何愿意帮助我的人

【问题讨论】:

  • 关联数组没有任何顺序。
  • @DonCallisto:这完全是错误的。数组也是列表,因此肯定有明确的顺序。
  • Sort array using another array 的可能重复项
  • 如果你的数组是数字的,那么使用 array_splice 来做你想做的事情会简单得多:php.net/manual/en/function.array-splice.php
  • 是的,如果是数字,那么解决方案会很简单 :) 这就是我询问堆栈溢出的原因,因为关联数组导致它变得复杂

标签: php


【解决方案1】:
$arr = array(
  'a' => 1,
  'b' => 2,
  'move me' => 9,
  'c' => 3,
  'd' => 4,
);

嘿,我想在 ['b'] 之前移动 ['move me']。我只需要 4 行代码就可以搞定!

$i = 0; foreach($arr as &$val) $val = array('sort' => (++$i * 10), 'val' => $val);
$arr['move me']['sort'] = $arr['b']['sort'] - 5;
uasort($arr, function($a, $b) { return $a['sort'] > $b['sort']; });
foreach($arr as &$val) $val = $val['val'];




我制作了一个易于使用的功能:
function move_item(&$ref_arr, $key1, $move, $key2 = null)
{
  $arr = $ref_arr;
  if($key2 == null) $key2 = $key1;
  if(!isset($arr[$key1]) || !isset($arr[$key2])) return false;

  $i = 0; foreach($arr as &$val) $val = array('sort' => (++$i * 10), 'val' => $val);

  if(is_numeric($move))
  {
    if($move == 0 && $key1 == $key2) return true;
    elseif($move == 0) { $tmp = $arr[$key1]['sort']; $arr[$key1]['sort'] = $arr[$key2]['sort']; $arr[$key2]['sort'] = $tmp; }
    else $arr[$key1]['sort'] = $arr[$key2]['sort'] + ($move * 10 + ($key1 == $key2 ? ($move < 0 ? -5 : 5) : 0));
  }
  else
  {
    switch($move)
    {
      case 'up':     $arr[$key1]['sort'] = $arr[$key2]['sort'] - ($key1 == $key2 ? 15 : 5); break;
      case 'down':   $arr[$key1]['sort'] = $arr[$key2]['sort'] + ($key1 == $key2 ? 15 : 5); break;
      case 'top':    $arr[$key1]['sort'] = 5; break;
      case 'bottom': $arr[$key1]['sort'] = $i * 10 + 5; break;
      default: return false;
    }
  }
  uasort($arr, function($a, $b) { return $a['sort'] > $b['sort']; });
  foreach($arr as &$val) $val = $val['val'];
  $ref_arr = $arr;
  return true;
}


例子:

move_item($arr, 'move me', 'up'); //move it one up
move_item($arr, 'move me', 'down'); //move it one down
move_item($arr, 'move me', 'top'); //move it to top
move_item($arr, 'move me', 'bottom'); //move it to bottom

move_item($arr, 'move me', -1); //move it one up
move_item($arr, 'move me', 1); //move it one down
move_item($arr, 'move me', 2); //move it two down

move_item($arr, 'move me', 'up', 'b'); //move it before ['b']
move_item($arr, 'move me', -1, 'b'); //move it before ['b']
move_item($arr, 'move me', 'down', 'b'); //move it after ['b']
move_item($arr, 'move me', 1, 'b'); //move it after ['b']
move_item($arr, 'move me', 2, 'b'); //move it two positions after ['b']

//Special syntax, to swap two elements:
move_item($arr, 'a', 0, 'd'); //Swap ['a'] with ['d']


我希望这可以帮助很多人,因为它是一个很棒的功能! :D

【讨论】:

  • 我已经添加了这个,所以如果数组包含空值,它将起作用 - $arr = array_map(function($v){ return (is_null($v)) ? "" : $v; },$arr);认为有更好的方法吗?
  • 加入我的项目并在第一次尝试时就运行起来真是太棒了。
【解决方案2】:

我最喜欢 luky 的回答,但它需要指定所有键。大多数时候,您只想在数组的开头订购键的子集。此功能将有所帮助:

function reorder_assoc_array(
  $cur,   // current assoc array 
  $order  // array conaining ordered (subset of) keys in $cur
) {
  $result = [];
  // first copy ordered key/values to result array
  foreach($order as $key) {
    $result[$key] = $cur[$key];
    // unset key in original array
    unset($cur[$key]);
  }
  // ... then copy all remaining keys that were not given in $order
  foreach($cur as $key => $value) {
    $result[$key] = $value;
  }
  return $result;
}

例子:

$assoc_arr = [
  'b' => 'bbb',
  'a' => 'aaa',
  'c' => 'ccc',
  'd' => 'ddd'
];

// suppose we want to swap the first two keys and leave the remaining keys as is
$assoc_arr = reorder_assoc_array($assoc_arr, ['a', 'b']);

// ... the order of keys is now a, b, c, d

【讨论】:

    【解决方案3】:

    例如,对于自定义排序,您可以创建一个数组,该数组是键的所需顺序,然后将值与它们相关联。示例:

    $input = array("a"=>"Element A","b"=>"Element B","c"=>"Element C");
    $order = array("c","a","b");
    $out = array();
    foreach($order as $k) {
        $out[$k] = $input[$k];
    }
    

    $out 中的元素将按照指定的顺序排列。

    【讨论】:

    • 这对我的问题不起作用。我需要将一个元素移动到另一个元素之前或之后。所以我的方法只会得到两个键
    【解决方案4】:

    如果你想交换两个值,你可以做一个这样的函数:

    function array_swap($key1, $key2, $array) {
            $newArray = array ();
            foreach ($array as $key => $value) {
                if ($key == $key1) {
                    $newArray[$key2] = $array[$key2];
                } elseif ($key == $key2) {
                    $newArray[$key1] = $array[$key1];
                } else {
                    $newArray[$key] = $value;
                }
            }
            return $newArray;
        }
    

    【讨论】:

    • 感谢您的回答,但我还需要移动键,而不仅仅是值
    【解决方案5】:

    这里有很多困难的方法 :) 事实上,你可以利用array_slice() 的保留密钥功能。

    $new_element = array('new_key' => 'value');
    
    // if needed, find the insertion index by key
    $index = array_search('key to search', array_keys($old_array));
    
    // add element at index (note the last array_slice argument)
    $new_array = array_slice($old_array, 0, $index+1, true) + $new_element + array_slice($old_array, $index+1, null, true);
    

    【讨论】:

      【解决方案6】:

      array_splice 不幸的是不适用于关联数组,所以这里有点混乱:

      $keys = array_keys($arr);
      $values = array_values($arr);
      
      $keyIndex = array_search($someKey, $keys);
      array_splice($keys, $keyIndex, 1);
      array_splice($values, $keyIndex, 1);
      
      $insertIndex = 1;
      array_splice($keys, $insertIndex, 0, array($someKey));
      array_splice($values, $insertIndex, 0, array($arr[$someKey]));
      
      $arr = array_combine($keys, $values);
      

      【讨论】:

        【解决方案7】:

        我在这里根据一个答案制作了一个函数。它需要对 assoc 数组进行排序,再加上应该使用它的键数组

        // $data = array of assoc array
        // $newKeysOrder = array("c","a","b");
        function resort_assoc_array_by_keys($data, $newKeysOrder) {
          foreach($data as $v) {
            $out = [];
            foreach($newKeysOrder as $k) {
              $out[$k] = $v[$k];
            }  
            $new[] = $out;
          }
          return $new;
        }
        

        【讨论】:

          猜你喜欢
          • 2013-02-12
          • 1970-01-01
          • 2011-02-26
          • 2011-01-28
          • 1970-01-01
          • 1970-01-01
          • 2012-08-25
          • 2014-05-22
          • 1970-01-01
          相关资源
          最近更新 更多