Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 使用映射数组与带有部分键的数组合并关联数组(支持命名参数)_Php_Arrays - Fatal编程技术网

Php 使用映射数组与带有部分键的数组合并关联数组(支持命名参数)

Php 使用映射数组与带有部分键的数组合并关联数组(支持命名参数),php,arrays,Php,Arrays,这是我正在开发的一个模板系统,专门用于支持我的模板过滤器和函数中的命名参数 我将使用我的escapeHtml过滤器(基本上是本机PHP中的htmlspecialchars)尽我所能直截了当地解释问题 考虑一下,我有这个映射数组(这将根据调用的函数或过滤器而改变) 为了解释这一点,第一级键(如标志是输入名称,类型是支持的输入类型(这对这个问题不重要)。默认值只是在输入中未提供任何值时使用的默认值。现在,我正在开发的代码允许一些我必须映射到这个数组的输入,输入可以被索引(数字),或者使用与上面输入名

这是我正在开发的一个模板系统,专门用于支持我的模板过滤器和函数中的命名参数

我将使用我的escapeHtml过滤器(基本上是本机PHP中的
htmlspecialchars
)尽我所能直截了当地解释问题

考虑一下,我有这个映射数组(这将根据调用的函数或过滤器而改变)

为了解释这一点,第一级键(如
标志
是输入名称,
类型
是支持的输入类型(这对这个问题不重要)。
默认值
只是在输入中未提供任何值时使用的默认值。现在,我正在开发的代码允许一些我必须映射到这个数组的输入,输入可以被索引(数字),或者使用与上面输入名称匹配的键。映射数组的索引输入顺序正确或符合预期

所以一些输入的例子

$input = array(
    'string' => 'hello',
     0 => 'ISO-8859-1',
    1 => false,
    'flags' => 3
 );
现在我需要将它与映射数组协调,这样输出就是

$output = array(
    'string' => 'hello',
    'flags' => 3
    'encoding' => 'ISO-8859-1',
    'double_encode' => false,
);
因此,如果您了解到目前为止,我需要带有键的项来匹配映射数组,并按照它们出现的顺序添加任何剩余元素(数字索引)。有一些错误检查涉及,但我并不过分担心这一点在目前

我确实做到了这一点,但它花费了我大约70行代码和3个循环,因此如果你能克服这一点,作为额外的奖励,你可以在项目源代码中获得学分:)。我还没有添加任何代码(目前非常不稳定),但Git回购协议如下:

也就是说,我在自述和维基上添加了很多东西。下面这一点对问题并不重要,但应该提供一些内容。在我的模板系统中,过滤器是以这种方式在模板源中调用的

{ $variable|escapeHtml } //no params
{ $variable|escapeHtml( ) } //no params
{ $variable|escapeHtml( 3, 'ISO-8859-1', false) } //indexed params
{ $variable|escapeHtml( flags=3, double_encode=true, encoding='ISO-8859-1') } //intended support for named params
{ $variable|escapeHtml( 'ISO-8859-1', false, flags = 3) } //support for mixed params as in the example
在上述过滤器的情况下,第一个输入是变量
$variable
的值,现在这将最终由我的模板系统编译成一个PHP类,看起来像这样

    $output .= $this->isPrintable(
        $this->_executeCallable( [
            400,/* Token::T_FILTER */
            'escapehtml',/* TagType */
            ['string'=>$this->get('variable'), 'flags'=>3, 'encoding'=>'ISO-8859-1', 'double_encode'=>true ]
        ] ),
        'for variable[ T_VARIABLE_TAG::$variable ] on Line[ 2 ] In Template[ test.tpl ]'
    );
不用说,我希望能用少于3个循环和70多行代码得到一个答案

谢谢

编辑::这大约是我现在所拥有的,当输入比混合类型更简单或基本上与地图数字索引匹配时,这是为了节省一些时间。此外,我在这里检查缺少必需参数时出错,即输入中没有的参数在映射数组中没有默认值

    echo '<pre>';

    $map = array(
            'string' => array(
                    'type' => 'string'
            ),
            'flags' => array(
                    'type' => 'integer',
                    'default' => 11
            ),
            'encoding' => array(
                    'type' => 'string',
                    'default' => 'UTF-8'
            ),
            'double_encode' => array(
                    'type' => 'boolean',
                    'default' => true
            )
    );

    $input = array(
            'string' => 'hello',
            0 => 'ISO-8859-1',
            1 => false,
            'flags' => 3
    );

    /* //simple indexed input
    $input = array(
        'hello',
        3,
        'ISO-8859-1',
        false
    );
    */

    $isNumeric = true;
    foreach ( $input as $k => $v){
        if(!is_numeric($k)){
            $isNumeric = false;
        }
    }

    if( !$isNumeric || count( $map ) != count( $input )){
        $numeric = array();
        $assoc = array();
        //split input into associative and indexed keys
        foreach ( $input as $k => $v){
            if(!is_numeric($k)){
                $assoc[$k] = $v;
            }else{
                $numeric[] = $v;
            }
        }

        //setup a dummy array based off the map keys
        $output = array_fill_keys( array_keys( $map ), '_UNSET_');

        foreach( $output as $key => &$value ){
            if( isset( $assoc[ $key ] ) ){
                $value = $assoc[ $key ];
                unset( $assoc[$key] );
            }else if( count( $numeric ) > 0 ){
                $value = array_shift( $numeric );
            }else{
                if( isset( $map[ $key ][ 'default' ]) ){
                    $value = $map[ $key ][ 'default' ];
                }else{
                    //throw error for missing required param
                    die( "missing required param $key on ".__LINE__);
                }
            }
        }

        if( count( $assoc ) > 0 ){
            var_export( $assoc );
            die( "unused inputs on ".__LINE__);
        }

        if( count( $numeric ) > 0 ){
            var_export( $numeric );
            die( "unused inputs on ".__LINE__);
        }
    }else{
        $output = array_combine(array_keys( $map ), $input);
    }


    var_export( $output );
array (
  'encoding' => 'ISO-8859-1',
  'double_encode' => false,
  'string' => 'test',
  'flags' => 3,
)
在第二个示例中,我得到了一个错误,因为我缺少一个必需的值:

在第三种情况下:

array (
    'string' => 'hello',
    'flags' => 3,
    'encoding' => 'ISO-8859-1',
    'double_encode' => false,
)
如果有额外的,他们只是忽略了目前,我应该检查他们,但这不是什么大不了的事。我只是想避免很多框架都有的那个神奇的黑匣子。我唯一可以添加的另一件事是将它们按正确的顺序排序,但我不确定是否需要,这取决于我如何实现调用函数等


无论如何,谢谢,

这会处理映射,处理缺少的参数,在缺少参数或其值为空时应用默认值:

array_merge(
  array_replace(
    array_intersect_key($mapping, $input),
    array_intersect_key($input, $mapping)
  ),
  array_combine(
      array_keys(array_diff_key($mapping, $input)), 
      array_values(array_diff_key($input, $mapping))
  )
)

var\u导出($output)


还没有测试过,但我认为这应该接近你想要的


我觉得你应该分享这3个循环和70多行代码…我会给我几分钟的时间来解决一些依赖性。实际上,我必须在数组_组合之前进行错误检查,我喜欢这个答案,因为我想用类似的方式来做,只是我无法理解。实际上这很好,我已经做了所需的更改,以检查是否缺少具有默认值的参数。有了这个,它比我原来的小不了多少。我可能需要做一些基准测试,看看哪一个更快,尽管这可能会帮助我删除原始阵列的一些部分。谢谢,唯一真正的问题是,如果两个阵列的长度不相同,array_combine将发出警告,因此我可以使用到那里的所有内容。我也不需要包含默认值,我只需要确保没有默认值的没有丢失。我可以修改映射,默认情况下我使用反射来生成它。@derp,很抱歉我错过了这一部分,但如果有额外的映射,它也可以走另一条路,我想我可以将所有这些合并到一个简单的循环中,而不是数组合并&数组合并&数组行走部分,毫无疑问这是一个棘手的部分,不过前面的第一部分很好。这是可行的,但是对于我的用例来说,它太精简了,我必须做一些变化和错误检查,并且没有办法将它们挂接到中。DAPOR-声明、分配、处理、输出、返回。声明并分配数组,然后在分配后使用array_walk或其他数组转换来验证数据。
array (
  'encoding' => 'ISO-8859-1',
  'double_encode' => false,
  'string' => 'test',
  'flags' => 11,
)
// Get the named parameters from the input array.
$namedParams = array_intersect_key($input, $mapping);

// Get the mapping keys for those missing from input.
$unmappedKeys = array_keys(array_diff_key($mapping, $input));

// Get the unnamed parameters from the input.
// Pad the array with null placeholders for those missing.
$numberedParams = array_pad(
    array_diff_key($input, $mapping),
    count($unmappedKeys),
    null);

// Map keys to the unnamed parameters.
$mappedParams = array_combine($unmappedKeys, $numberedParams);

// Merge.
$output = array_merge($namedParams, $mappedParams);

// Apply defaults from the $mapping array to parameters with null values.
array_walk(
    $output,
    function (&$v, $k, $m) {
        $v = is_null($v) ? $m[$k]['default'] : $v;
    },
    $mapping
);
array (
    'string' => 'hello',
    'flags' => 3,
    'encoding' => 'ISO-8859-1',
    'double_encode' => false,
)
array_merge(
  array_replace(
    array_intersect_key($mapping, $input),
    array_intersect_key($input, $mapping)
  ),
  array_combine(
      array_keys(array_diff_key($mapping, $input)), 
      array_values(array_diff_key($input, $mapping))
  )
)