php 切换关联数组中的两项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2448345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 06:32:00  来源:igfitidea点击:

Switch two items in associative array

phparrays

提问by leon.nk

Example:

例子:

$arr = array(
  'apple'      => 'sweet',
  'grapefruit' => 'bitter',
  'pear'       => 'tasty',
  'banana'     => 'yellow'
);

I want to switch the positions of grapefruit and pear, so the array will become

我想把柚子和梨的位置调换一下,这样数组就变成了

$arr = array(
  'apple'      => 'sweet',
  'pear'       => 'tasty',
  'grapefruit' => 'bitter',
  'banana'     => 'yellow'
)

I know the keys and values of the elements I want to switch, is there an easy way to do this? Or will it require a loop + creating a new array?

我知道要切换的元素的键和值,有没有简单的方法可以做到这一点?还是需要循环+创建新数组?

Thanks

谢谢

采纳答案by OverLex

There is no easy way, just a loop or a new array definition.

没有简单的方法,只有一个循环或一个新的数组定义。

回答by metti

Just a little shorter and less complicated than the solution of arcaneerudite:

只是比 Arcaneerudite 的解决方案更短更简单:

<?php
if(!function_exists('array_swap_assoc')) {
    function array_swap_assoc($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;
    }
}

$array = $arrOrig = array(
    'fruit' => 'pear',
    'veg' => 'cucumber',
    'tuber' => 'potato',
    'meat' => 'ham'
);

$newArray = array_swap_assoc('veg', 'tuber', $array);

var_dump($array, $newArray);
?>

Tested and works fine

经测试并正常工作

回答by ttk

Here's my version of the swap function:

这是我的交换函数版本:

function array_swap_assoc(&$array,$k1,$k2) {
  if($k1 === $k2) return;  // Nothing to do

  $keys = array_keys($array);  
  $p1 = array_search($k1, $keys);
  if($p1 === FALSE) return;  // Sanity check...keys must exist

  $p2 = array_search($k2, $keys);
  if($p2 === FALSE) return;

  $keys[$p1] = $k2;  // Swap the keys
  $keys[$p2] = $k1;

  $values = array_values($array); 

  // Swap the values
  list($values[$p1],$values[$p2]) = array($values[$p2],$values[$p1]);

  $array = array_combine($keys, $values);
}

回答by dazz

if the array comes from the db, add a sort_order field so you can always be sure in what order the elements are in the array.

如果数组来自数据库,请添加 sort_order 字段,以便您始终可以确定元素在数组中的顺序。

回答by keithjgrant

This may or may not be an option depending on your particular use-case, but if you initialize your array with null values with the appropriate keys before populating it with data, you can set the values in any order and the original key-order will be maintained. So instead of swapping elements, you can prevent the need to swap them entirely:

根据您的特定用例,这可能是也可能不是一个选项,但是如果您在使用数据填充数组之前使用适当的键使用空值初始化数组,您可以按任何顺序设置值,原始键顺序将得到维护。因此,您可以避免完全交换元素,而不是交换元素:

$arr = array('apple' => null,
             'pear' => null,
             'grapefruit' => null,
             'banana' => null);

...

...

$arr['apple'] = 'sweet';
$arr['grapefruit'] = 'bitter'; // set grapefruit before setting pear
$arr['pear'] = 'tasty';
$arr['banana'] = 'yellow';
print_r($arr);

>>> Array
(
    [apple] => sweet
    [pear] => tasty
    [grapefruit] => bitter
    [banana] => yellow
)

回答by arcaneerudite

Not entirely sure if this was mentioned, but, the reason this is tricky is because it's non-indexed.

不完全确定是否提到了这一点,但是,这很棘手的原因是因为它没有编入索引。

Let's take:

让我们来:

$arrOrig = array(
  'fruit'=>'pear',
  'veg'=>'cucumber',
  'tuber'=>'potato'
);

Get the keys:

获取钥匙:

$arrKeys = array_keys($arrOrig);
print_r($arrKeys);
Array(
 [0]=>fruit
 [1]=>veg
 [2]=>tuber
)

Get the values:

获取值:

$arrVals = array_values($arrOrig);
print_r($arrVals);
Array(
  [0]=>pear
  [1]=>cucumber
  [2]=>potato
)

Now you've got 2 arrays that are numerical. Swap the indices of the ones you want to swap, then read the other array back in in the order of the modified numerical array. Let's say we want to swap 'fruit' and 'veg':

现在你有 2 个数字数组。交换要交换的索引的索引,然后按照修改后的数值数组的顺序读回另一个数组。假设我们要交换 'fruit' 和 'veg':

$arrKeysFlipped = array_flip($arrKeys);
print_r($arrKeysFlipped);
Array (
 [fruit]=>0
 [veg]=>1
 [tuber]=>2
)
$indexFruit = $arrKeysFlipped['fruit'];
$indexVeg = $arrKeysFlipped['veg'];
$arrKeysFlipped['veg'] = $indexFruit;
$arrKeysFlipped['fruit'] = $indexVeg;
print_r($arrKeysFlipped);
Array (
 [fruit]=>1
 [veg]=>0
 [tuber]=>2
)

Now, you can swap back the array:

现在,您可以换回数组:

$arrKeys = array_flip($arrKeysFlipped);
print_r($arrKeys);
Array (
 [0]=>veg
 [1]=>fruit
 [2]=>tuber
)

Now, you can build an array by going through the oringal array in the 'order' of the rearranged keys.

现在,您可以通过按重新排列的键的“顺序”遍历原始数组来构建数组。

$arrNew = array ();
foreach($arrKeys as $index=>$key) {
  $arrNew[$key] = $arrOrig[$key];
}
print_r($arrNew);
Array (
 [veg]=>cucumber
 [fruit]=>pear
 [tuber]=>potato
)

I haven't tested this - but this is what I'd expect. Does this at least provide any kind of help? Good luck :)

我还没有测试过这个 - 但这是我所期望的。这至少提供了任何帮助吗?祝你好运 :)

You could put this into a function $arrNew = array_swap_assoc($key1,$key2,$arrOld);

你可以把它放到一个函数中 $arrNew = array_swap_assoc($key1,$key2,$arrOld);

<?php
if(!function_exists('array_swap_assoc')) {
    function array_swap_assoc($key1='',$key2='',$arrOld=array()) {
       $arrNew = array ();
       if(is_array($arrOld) && count($arrOld) > 0) {
           $arrKeys = array_keys($arrOld);
           $arrFlip = array_flip($arrKeys);
           $indexA = $arrFlip[$key1];
           $indexB = $arrFlip[$key2];
           $arrFlip[$key1]=$indexB;
           $arrFlip[$key2]=$indexA;
           $arrKeys = array_flip($arrFlip);
           foreach($arrKeys as $index=>$key) {
             $arrNew[$key] = $arrOld[$key];
           }
       } else {
           $arrNew = $arrOld;
       }
       return $arrNew;
    }
}
?>

WARNING: Please test and debug this before just using it - no testing has been done at all.

警告:请在使用前对其进行测试和调试 - 根本没有进行任何测试。

回答by Bryan Clark

yeah I agree with Lex, if you are using an associative array to hold data, why not using your logic handle how they are accessed instead of depending on how they are arranged in the array.

是的,我同意 Lex,如果您使用关联数组来保存数据,为什么不使用您的逻辑处理它们的访问方式,而不是取决于它们在数组中的排列方式。

If you really wanted to make sure they were in a correct order, trying creating fruit objects and then put them in a normal array.

如果您真的想确保它们的顺序正确,请尝试创建水果对象,然后将它们放入普通数组中。

回答by Xeoncross

There is no easy way to do this. This sounds like a slight design-logic error on your part which has lead you to try to do this when there is a better way to do whatever it is you are wanting to do. Can you tell us why you want to do this?

没有简单的方法可以做到这一点。这听起来像是您的一个轻微的设计逻辑错误,这导致您在有更好的方法来做您想做的任何事情时尝试这样做。你能告诉我们你为什么要这样做吗?

You say that I know the keys and values of the elements I want to switchwhich makes me think that what you really want is a sorting function since you can easily access the proper elements anytime you want as they are.

你这么说I know the keys and values of the elements I want to switch让我觉得你真正想要的是排序功能,因为你可以随时轻松访问适当的元素。

$value = $array[$key];

If that is the case then I would use sort(), ksort()or one of the many other sorting functions to get the array how you want. You can even use usort()to Sort an array by values using a user-defined comparison function.

如果是这种情况,那么我将使用sort()ksort()或许多其他排序函数之一来获取您想要的数组。您甚至可以使用usort()Sort an array by values using a user-defined comparison function.

Other than that you can use array_replace()if you ever need to swap values or keys.

除此之外,如果您需要交换值或键,您可以使用array_replace()

回答by Andrey

Classical associative array doesn't define or guarantee sequence of elements in any way. There is plain array/vector for that. If you use associative array you are assumed to need random access but not sequential. For me you are using assoc array for task it is not made for.

经典关联数组不以任何方式定义或保证元素的序列。有简单的数组/向量。如果您使用关联数组,则假定您需要随机访问而不是顺序访问。对我来说,你使用的是 assoc 数组来完成它不适合的任务。

回答by Steve

fwiw here is a function to swap two adjacent items to implement moveUp() or moveDown() in an associative array without foreach()

fwiw 这里是一个函数,用于交换两个相邻项以在没有 foreach() 的关联数组中实现 moveUp() 或 moveDown()

/**
 * @param array  $array     to modify
 * @param string $key       key to move
 * @param int    $direction +1 for down | -1 for up
 * @return $array
 */
protected function moveInArray($array, $key, $direction = 1)
{
    if (empty($array)) {
        return $array;
    }
    $keys  = array_keys($array);
    $index = array_search($key, $keys);
    if ($index === false) {
        return $array; // not found
    } 
    if ($direction < 0) {
        $index--;
    }
    if ($index < 0 || $index >= count($array) - 1) {
        return $array; // at the edge: cannot move
    } 

    $a          = $keys[$index];
    $b          = $keys[$index + 1];
    $result     = array_slice($array, 0, $index, true);
    $result[$b] = $array[$b];
    $result[$a] = $array[$a];
    return array_merge($result, array_slice($array, $index + 2, null, true)); 
}