据说php实现自由合併数组并排序,深刻剖判PHP中

作者: 新金沙平台  发布:2019-07-14

最近做了一个项目,其中有这样一个需求要实现,原有帖子列表A,现在需要在A中推广新业务B,那么需要在A列表中1:1混合B中的数据,随机混合,但是需要保持A和B两列原来的数据排序,具体详情请看下文。

foreach是PHP中很常用的一个用作数组循环的控制语句。
因为它的方便和易用,自然也就在后端隐藏着很复杂的具体实现方式(对用户透明)
今天,我们就来一起分析分析,foreach是如何实现数组(对象)的遍历的。
我们知道PHP是一个脚本语言,也就是说,用户编写的PHP代码最终都是会被PHP解释器解释执行,
特别的,对于PHP来说,所有的用户编写的PHP代码,都会被翻译成PHP的虚拟机ZE的虚拟指令(OPCODES)来执行,不论细节的话,就是说,我们所编写的任何PHP脚本,都会最终被翻译成一条条的指令,从而根据指令,由相应的C编写的函数来执行。

PHP 中的数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。此类型在很多方面做了优化,因此可以把它当成真正的数组,或列表(向量),散列表(是映射的一种实现),字典,集合,栈,队列以及更多可能性。由于数组元素的值也可以是另一个数组,树形结构和多维数组也是允许的。

原理

那么foreach会被翻译成什么样子呢?

array

获知总共元素数量N;
for循环N次,取随机数;
根据随机数依次从头获取A或B的值,推入新数组中;

foreach($arr as $key => $val){
   echo $key . '=>' . $val . "n";
}

(PHP 4, PHP 5)

代码:

在词法分析阶段,foreach会被识别为一个TOKEN:T_FOREACH,
在语法分析阶段,会被规则:

array — 新建一个数组

//随机合并两个数组元素,保持原有数据的排序不变(即各个数组的元素在合并后的数组中排序与自身原来一致)
function shuffleMergeArray() {
  $mergeArray = array();
  $sum = count($array1)   count($array2);
  for ($k = $sum; $k > 0; $k--) {
    $number = mt_rand(1, 2);
    if ($number == 1) {
      $mergeArray[] = $array2 ? array_shift($array2) : array_shift($array1);
    } else {
      $mergeArray[] = $array1 ? array_shift($array1) : array_shift($array2);
    }
  }
  return $mergeArray;
}
 unticked_statement: //没有被绑定ticks的语句
   //有省略
  |  T_FOREACH '(' variable T_AS
    { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 1 TSRMLS_CC); }
    foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
    foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
  |  T_FOREACH '(' expr_without_variable T_AS
    { zend_do_foreach_begin(&$1, &$2, &$3, &$4, 0 TSRMLS_CC); }
    variable foreach_optional_arg ')' { zend_check_writable_variable(&$6); zend_do_foreach_cont(&$1, &$2, &$4, &$6, &$7 TSRMLS_CC); }
    foreach_statement { zend_do_foreach_end(&$1, &$4 TSRMLS_CC); }
   //有省略
;

说明

示例:

仔细分析这段语法规则,我们可以发现,对于:

复制代码 代码如下:

合并前的数组:

foreach($arr as $key => $val){
echo $key . ‘=>' . $val .”n”;
}

array array ([ mixed $... ] )

$array1 = array(1, 2, 3, 4);
$array2 = array('a', 'b', 'c', 'd', 'e');

会被分析为:

返回根据参数建立的数组。参数可以用 => 运算符给出索引。关于数组是什么的信息请阅读数组一节。

合并后的数据:

   T_FOREACH '(' variable T_AS  { zend_do_foreach_begin('foreach', '(', $arr, 'as', 1 TSRMLS_CC); }
  foreach_variable foreach_optional_arg(T_DOUBLE_ARROW foreach_variable)  ')' { zend_do_foreach_cont('foreach', '(', 'as', $key, $val TSRMLS_CC); }
  foreach_satement {zend_do_foreach_end('foreach', 'as');}

Note:

$mergeArray = array (
 0 => 'a',
 1 => 1,
 2 => 'b',
 3 => 2,
 4 => 'c',
 5 => 'd',
 6 => 3,
 7 => 4,
 8 => 'e',
)

然后,让我们来看看foreach_statement:
它其实就是一个代码块,体现了我们的 echo $key . ‘=>' . $val .”n”;
T_ECHO expr;

array() 是一个语言结构,用于字面上表示数组,不是常规的函数。

php数组随机排序

显然,实现foreach的核心就是如下3个函数:

语法“index => values”,用逗号分开,定义了索引和值。索引可以是字符串或数字。如果省略了索引,会自动产生从 0 开始的整数索引。如果索引是整数,则下一个产生的索引将是目前最大的整数索引

本文由新金沙平台发布于新金沙平台,转载请注明出处:据说php实现自由合併数组并排序,深刻剖判PHP中

关键词: 新金沙平台