PHP是否具有内置函数来在关联数组的现有键之前插入键?

时间:2017-07-24 17:59:28

标签: php arrays multidimensional-array

近一年来,我们的一个应用程序需要检查关联数组的值并将布尔值映射到新数组:

$original_array['key_1'] = $value_1;
$original_array['key_2'] = $value_2;
.
.
.
$original_array['key_n'] = $value_n;

$mapped_array = array();

foreach($original_array as $k=>$v) {
    $mapped_array[$k] = $this->checkIfValid($v); // Boolean returned 
}

我没有迹象表明重新映射的$original_array版本需要是多维的。但是,重新映射的$original_array版本(即$mapped_array)的结构最近被我们需要稍微不同结构的前端开发人员强制改变。现在, $mapped_array成员的一些需要是多维的:

$mapped_array['prefix-key_2']['key_2'] = $value_2; // note the value of the prefix_key and the key do not fit any type of pattern where you can write a function to generate the prefix key given the key

这显然破坏了foreach循环的有效性。我知道我可以像这样做一些hackish来重新映射原始数组,使其具有1或2维的键结构,如下所示:

$key_prefixes = array('prefix-key_2' => 'key_2');

foreach($original_array as $k=>$v) {
    if (!isset($key_prefixes[$k])) {
        $mapped_array[$k] = $this->checkIfValid($v); // Boolean returned 
    } else {
        switch($k) {
            case 'prefix-key_2':
                $mapped_array[$k][$key_prefixes[$k]] = $v;
            break;
            .
            .
            .
            etc.
        }
    }
}

但是,我知道情况会变得更复杂,因为重映射数组的维数会慢慢增加到2以上。类似于使用字符串连接,我可以很容易地在现有字符串前加/附加:

$original_string = $value;
$remapped_string = $prepend . $value;

PHP中是否存在在现有密钥之前插入密钥的功能,从而轻松定制重映射数组的维数?像这样:

$arr = array('key_n' => $value_n);// so $arr['key_n'] = $value_n

array_insert_key('inserted_prefix', $arr);

//Now $arr looks like this ---> $arr['inserted_prefix']['key_n'] = $value_n

4 个答案:

答案 0 :(得分:2)

我不确定我是否理解正确,所以如果我不理解:请在下面发表评论。但是,如果我看看你的(引用)'像这样的hackish'的例子,我认为你正在寻找这样的东西:

function createMappedArray($inputArray) 
{
    $result = array();
    foreach($inputArray as $k => $v) {
        if (is_array($v)) {
           $result[$k] = createMappedArray($v); // Calling itself (recursion)
        } else {
           $result[$k] = checkIfValid($v);
        }
    }
    return $result;
}
$mapped_array = createMappedArray($original_array);

甚至是递归解决方案,因此如果添加了超过2个级别,您的代码将来会证明:

$original_array =
Array
(
    [key1] => 8
    [prefix-key_2] => Array
        (
            [key2] => 10
        )

    [key3] => 2
    [another_prefix] => Array
        (
            [key4] => 1
        )

)

// Will produce (for a checkValid-rule 'value > 5')
$mapped_array =
Array
(
    [key1] => true
    [prefix-key_2] => Array
        (
            [key2] => true
        )

    [key3] => false
    [another_prefix] => Array
        (
            [key4] => false
        )

)

使用演示数据

REST API

答案 1 :(得分:1)

对我而言,关于PHP及其数组最令人困惑的是,PHP数组在“经典”意义上不是数组。 “经典”数组或列表是一个带有数字键的数字索引列表,它使整个结构有序。所以如果你有这样的东西:

$a1 = [];
$a1[10] = '##';
$a1[100] = '####';

echo count($a1) // 2

for ($i=0; $i < count($a1); $i++) echo $a1[$i]; //undefined index

什么没有多大意义。

你甚至可以使用字符串键进行混音:

$a1['key_1'] = '##';
$a1['key_2'] = '##';

现在最后一个问题是:那件事是如何订购的?根据键的顺序,按插入顺序,首先是字符串数字?老实说,我不知道,并且我声明如果一个人试图依赖那个神秘的命令会产生混淆。

所以我的建议是:不要试图坚持关联数组的顺序,创建一个可以预测的数组的数组。

您正在做的是:您创建了一个key_1, key_2, prefix-key_1等排序,连接到某些值,这些值可能是原始的或复杂的,具体取决于密钥。

这意味着头疼,因为很难预测顺序并在顶部添加任意数据类型。

因此,要获得或多或少可预测的顺序,您可以执行类似的操作:

$order = uasort(array_keys($yourarray), function ($k1, k2) { ..logic to create the order .. })

foreach ($order as $key) {
  $val = $yourarray[$key];
}

但是你还是要检查你是在处理伪造的还是复杂的数据,所以如果数据很复杂,你可以写一些具有重复性的东西,但是认真地说:花一些时间来重构代码

回答你的问题:没有内置功能可以在一个可能已订购的结构上插入一个密钥。

如果很难替换整个代码,你可能可以用类似于数组的东西来交换它的一部分,但事实并非如此。看看ArrayObjectArrayAccessIterator,您可能可以创建类/对象,它看起来像代码的数组,但跟踪每个类的顺序插入,迭代和验证。

答案 2 :(得分:1)

根据这个例子,您给出了:

  

$ arr = array('key_n'=&gt; $ value_n); //所以$ arr ['key_n'] = $ value_n

     

array_insert_key('inserted_prefix',$ arr);

     

//现在$ arr看起来像这样---&gt; $ arr ['inserted_prefix'] ['key_n'] = $ value_n

你可以用这个:

$arr = array('key_n' => $value_n);
$arr['inserted_prefix'] = array('key_n' => $arr['key_n']);

/* $arr is now:
 *     array(
 *         'key_n' => $value_n,
 *         'inserted_prefix' => array(
 *             'key_n' => $value_n
 *         )
 *     )
 */

unset($arr['key_n']);

/* $arr is now:
 *     array(
 *         'inserted_prefix' => array(
 *             'key_n' => $value_n
 *         )
 *     )
 */

没有内置函数可以做到这一点,但您可以轻松地将其包装在自定义函数中:

function wrap_key($array, $key, $prefix) {
    $array[$prefix] = array($key => $array[$key]);
    unset($array[$key]);
    return $array;
}

$arr = array('key_n' => $value_n);
$arr = wrap_key($arr, 'key_n', 'inserted_prefix');

答案 3 :(得分:0)

PHP函数array_map()提供了一种循环遍历数组并处理它的简单方法。

对于原始数组,您的验证代码可能如下所示:

function validate($v) {
    return $this->checkIfValid($v);
}

$mapped_array = array_map('validate', $original_array);

对于一级数组,验证函数也可以是匿名的。但是,我们需要它为多级数组命名,因为它需要调用自身(通过将其名称传递给array_map()来间接调用)。

在这种形式中,很容易修改回调函数,以考虑到某些值本身就是数组。

function validate($v) {
    if (is_array($v)) {
        // Validate the array, return the validated result
        return array_map('validate', $v);
    } else {
        // Regular value, validate as usual
        return $this->checkIfValid($v);
    }
};

// The user code doesn't need to change
$mapped_array = array_map('validate', $original_array);

您也可以将上述验证函数作为使用它的类的方法。在这种情况下,您必须在上面'validate'的调用中将array($this, 'validate')替换为array_map()并制作新方法public(让array_map()访问它)。