【问题标题】:PHP extension iterate through arrayPHP扩展遍历数组
【发布时间】:2014-07-03 14:34:42
【问题描述】:

我开始编写 PHP 扩展,并希望了解如何循环遍历传递的数组(目的是按值更改数据值)。首选方法是 for 循环,以便我可以将 array1 与 array2 数据匹配,例如array1[0] 链接到 array2[0], [1] 和 [1] 等等...

有人可以帮忙吗?

modarray.c

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"

extern zend_module_entry modarray_module_entry;
#define phpext_modarray_ptr &modarray_module_entry

PHP_FUNCTION(modarray);

static function_entry modarray_functions[] = {
    PHP_FE(modarray, NULL)
    PHP_FE_END
};

zend_module_entry modarray_module_entry = {
  STANDARD_MODULE_HEADER,
  "modarray",
  modarray_functions,
  NULL,
  NULL,
  NULL,
  NULL,
  NULL,
  "0.1",
  STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(modarray)

PHP_FUNCTION(modarray)
{
  zval *val, *val2;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &val, &val2) == FAILURE){
    return;
  }

  SEPARATE_ZVAL(&val);
  SEPARATE_ZVAL(&val2);

  array_init(return_value);

  zval_add_ref(&val);
  zval_add_ref(&val2);
  add_next_index_zval(return_value, val);
  add_next_index_zval(return_value, val2);
}

PHP 代码

<?php
$array1 = array(1,2,3,4);
$array2 = array(5,6,7,8);
echo '<pre>';
print_r(modarray($array1,$array2));
echo '</pre>';
?>

PHP 输出

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

    [1] => Array
        (
            [0] => 5
            [1] => 6
            [2] => 7
            [3] => 8
        )

)

【问题讨论】:

标签: php c php-extension


【解决方案1】:

有两种方法可以做到这一点,一种是使用迭代 API 完全“手动”:

HashPosition pos;
zval *collection, **arg;
uint hash_key_type;
uint string_key_len;
ulong int_key;
char *string_key = NULL;

... get the collection from somewhere, e.g. argument parsing ...

while (!EG(exception) && zend_hash_get_current_data_ex(Z_ARRVAL_P(collection), (void **)&arg, &pos) == SUCCESS) {
    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(collection), &pos);
    MAKE_STD_ZVAL(key);
    hash_key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(collection), &string_key, &string_key_len, &int_key, 0, &pos);

    // Invoke e.g. zend_hash_update

    zend_hash_move_forward_ex(Z_ARRVAL_P(collection), &pos);
}

首选的替代方法是使用三个zend_hash_apply*() 函数和一个被认为更优雅的回调:

static int replace_value(zval **arg, zval ****params TSRMLS_DC)
{
    add_next_index_zval(params, val);

    return ZEND_HASH_APPLY_REMOVE;
}

zval *in, ***out;
... fill in from somewhere from somewhere, e.g. argument parsing ...
array_init(**out);
zend_hash_apply_with_argument(Z_ARRVAL_P(collection, (apply_func_arg_t) replace_value, params TSRMLS_CC);

注意:我没有在本地测试任何一个 sn-ps,而是从不同的地方复制它。

【讨论】:

    【解决方案2】:
    function multi_diff($arr1,$arr2){
      $result = array();
      foreach ($arr1 as $k=>$v){
        if(!isset($arr2[$k])){
          $result[$k] = $v;
        } else {
          if(is_array($v) && is_array($arr2[$k])){
            $diff = multi_diff($v, $arr2[$k]);
            if(!empty($diff))
              $result[$k] = $diff;
          }
        }
      }
      return $result;
    }
    
    //example:
    
    var_dump(multi_diff(
    
    array(
      "A"=>array(
        "A1"=>array('A1-0','A1-1','A1-2','A1-3'),
        "A2"=>array('A2-0','A2-1','A2-2','A2-3'),
        "A3"=>array('A3-0','A3-1','A3-2','A3-3')
      ),
      "B"=>array(
        "B1"=>array('B1-0','B1-1','B1-2','B1-3'),
        "B2"=>array('B2-0','B2-1','B2-2','B2-3'),
        "B3"=>array('B3-0','B3-1','B3-2','B3-3')
      ),
      "C"=>array(
        "C1"=>array('C1-0','C1-1','C1-2','C1-3'),
        "C2"=>array('C2-0','C2-1','C2-2','C2-3'),
        "C3"=>array('C3-0','C3-1','C3-2','C3-3')
      ),
      "D"=>array(
        "D1"=>array('D1-0','D1-1','D1-2','D1-3'),
        "D2"=>array('D2-0','D2-1','D2-2','D2-3'),
        "D3"=>array('D3-0','D3-1','D3-2','D3-3')
      )
    ),
    
    array(
      "A"=>array(
        "A1"=>array('A1-0','A1-1','A1-2','A1-3'),
        "A2"=>array('A2-0','A2-1','A2-2','A2-3'),
        "A3"=>array('A3-0','A3-1','A3-2')
      ),
      "B"=>array(
        "B1"=>array('B1-0','B1-2','B1-3'),
        "B2"=>array('B2-0','B2-1','B2-2','B2-3'),
        "B3"=>array('B3-0','B3-1','B3-3')
      ),
      "C"=>array(
        "C1"=>array('C1-0','C1-1','C1-2','C1-3'),
      ),
      "D"=>array(
        "D1"=>array('D1-0','D1-1','D1-2','D1-3'),
        "    "C3"=>array('C3-0','C3-1')
    D2"=>array('D2-0','D2-1','D2-2','D2-3'),
        "D3"=>array('D3-0','D3-1','D3-2','D3-3')
      )
    )
    
    ));
    

    【讨论】:

      【解决方案3】:

      您可以查看一些 C sn-ps 的 xarray 扩展或 php-src:https://github.com/c9s/xarray

      【讨论】:

        猜你喜欢
        • 2013-05-23
        • 2011-03-06
        • 1970-01-01
        • 1970-01-01
        • 2014-11-21
        • 2016-09-01
        • 2012-01-15
        • 2010-12-14
        • 1970-01-01
        相关资源
        最近更新 更多