首頁 後端開發 php教程 PHP数组的高级遍历和操作处理方法_PHP教程

PHP数组的高级遍历和操作处理方法_PHP教程

Jul 13, 2016 pm 04:57 PM
f foreach php 基於 處理 操作 陣列 方法 簡單 遍歷 進階

前面我讲过简单的数组遍历,这些基于foreach,for之类的语句,下面我来介绍数组的高级遍历方法介绍,各位朋友可参考,这些数组才真用于开发实用性能强,复杂也更高了。

PHP对数组的处理可以称为该语言最有吸引力的特性之一,它支持70多种数组相关的函数。不论你想翻转一个数组、判断某个值在数组中是否存在、将数组转换成一个字符串还是计算数组的大小,仅仅执行一个现有的函数就可以完成。然而也有一些数组相关的任务对开发者的要求就较高,仅仅知道手册有某个功能是不能解决的,这些任务就需要对PHP的原始特性有一些深入的理解,还需要一些解决问题的想象力。

多维关联数组排序
PHP提供了一些数组排序的函数,比如sort(), ksort(),和asort(),但是却没有提供对多维关联数组的排序。


比如这样的数组:

Array
(
  [0] => Array
    (
      [name] => chess
      [price] => 12.99
    )

  [1] => Array
    (
      [name] => checkers
      [price] => 9.99
    )

  [2] => Array
    (
      [name] => backgammon
      [price] => 29.99
    )
)

要将该数组按照升序排序,你需要自己写一个函数用于比较价格,然后将该函数作为回调函数传递给usort()函数来实现该功能:

 代码如下 复制代码

function comparePrice($priceA, $priceB){
    return $priceA['price'] - $priceB['price'];
}

usort($games, 'comparePrice');

执行了该程序片段,数组就会被排序,结果如下所示:

Array
(
  [0] => Array
    (
      [name] => checkers
      [price] => 9.99
    )

  [1] => Array
    (
      [name] => chess
      [price] => 12.99
    )

  [2] => Array
    (
      [name] => backgammon
      [price] => 29.99
    )
)

要将该数组按照降序排序,把comparePrice()函数里面的两个减的数调换位置就可以了。

逆序遍历数组
PHP的While循环和For循环是遍历一个数组最常用的方法。但是你怎样遍历像下面这个数组呢?

Array
(
  [0] => Array
    (
      [name] => Board
      [games] => Array
        (
          [0] => Array
            (
              [name] => chess
              [price] => 12.99
            )

          [1] => Array
            (
              [name] => checkers
              [price] => 9.99
            )
        )
    )
)

PHP标准库中有一个对集合的迭代器iterators类,它不仅仅能够用于遍历一些异构的数据结构(比如文件系统和数据库查询结果集),也可以对一些不知道大小的嵌套数组的遍历。比如对上面的数组的遍历,可以使用RecursiveArrayIterator迭代器进行:

 代码如下 复制代码

$iterator = new RecursiveArrayIterator($games);
iterator_apply($iterator, 'navigateArray', array($iterator));

function navigateArray($iterator) {
 while ($iterator->valid()) {
  if ($iterator->hasChildren()) {
   navigateArray($iterator->getChildren());
  } else {
   printf("%s: %s", $iterator->key(), $iterator->current());
  }
  $iterator->next();
 } 
}

执行该段代码会给出以下的结果:

name: Board
name: chess
price: 12.99
name: checkers
price: 9.99

过滤关联数组的结果
假定你得到了如下一个数组,但是你仅仅想操作价格低于$11.99的元素:

Array
(
  [0] => Array
    (
      [name] => checkers
      [price] => 9.99
    )

  [1] => Array
    (
      [name] => chess
      [price] => 12.99
    )

  [2] => Array
    (
      [name] => backgammon
      [price] => 29.99
    )
)

使用array_reduce()函数可以很简单的实现:

 代码如下 复制代码

function filterGames($game){
 return ($game['price'] }

$names = array_filter($games, 'filterGames');

array_reduce()函数会过滤掉不满足回调函数的所有的元素,本例子的回调函数就是filterGames。任何价格低于11.99的元素会被留下,其他的会被剔除。该代码段的执行结果:

Array
(
  [1] => Array
    (
      [name] => checkers
      [price] => 9.99
    )
)

对象转换成数组
一个需求就是将对象转换成数组形式,方法比你想象的简单很多,仅仅强制转换就可以了!例子:

 代码如下 复制代码

class Game {
 public $name;
 public $price;
}

$game = new Game();
$game->name = 'chess';
$game->price = 12.99;

print_r(array($game));

执行该例子就会产生如下结果:

Array
(
[0] => Game Object
  (
    [name] => chess
    [price] => 12.99
  )
)

将对象转换成数组会出现一些不可预料的副作用。比如上面的代码段,所有的成员变量都是public类型的,但是对于private私有变量的返回结果会变得不一样。下面是另外一个例子:

 代码如下 复制代码

class Game {
 public $name;
 private $_price;

 public function setPrice($price)  {
  $this->_price = $price;
 }
}

$game = new Game();
$game->name = 'chess';
$game->setPrice(12.99);

print_r(array($game));执行该代码片段:

Array
(
[0] => Game Object
  (
    [name] => chess
    [_price:Game:private] => 12.99
  )
)

正如你所看到的,为了进行区分,数组中保存的私有变量的key被自动改变了。

数组的“自然排序”
PHP对于“字母数字”字符串的排序结果是不确定的。举个例子,假定你有很多图片名称存放于数组中:

 代码如下 复制代码

$arr = array(
 0=>'madden2011.png',
 1=>'madden2011-1.png',
 2=>'madden2011-2.png',
 3=>'madden2012.png'
);

你怎样对这个数组进行排序呢?如果你用sort()对该数组排序,结果是这样的:

Array
(
    [0] => madden2011-1.png
    [1] => madden2011-2.png
    [2] => madden2011.png
    [3] => madden2012.png
)

有时候这就是我们想要的,但是我们想保留原来的下标怎么办?解决该问题可以使用natsort()函数,该函数用一种自然的方法对数组排序:

 代码如下 复制代码

$arr = array(
 0=>'madden2011.png',
 1=>'madden2011-1.png',
 2=>'madden2011-2.png',
 3=>'madden2012.png'
);

natsort($arr);
echo "

"; print_r($arr); echo "
登入後複製
";
?>

运行结果:

Array
(
    [1] => madden2011-1.png
    [2] => madden2011-2.png
    [0] => madden2011.png
    [3] => madden2012.png
)

遍历过程中的改值操作
引用操作符&
看下面这段代码中的$array数组,在foreach循环时对$value使用引用操作符,这样在循环中修改$value的值的时候,便将$array中对应的元素值修改了。

 代码如下 复制代码

$array = array("A"=>1, "B"=>1, "C"=>1, "D"=>1);
foreach($array as &$value)
    $value = 2;
print_r($array);
?>

上段代码的输出如下:

Array ( [A] => 2 [B] => 2 [C] => 2 [D] => 2 )
可以看到,$array中各个键对应的值都被修改成了2。看来这种方法确实奏效。

利用键值操作数组的元素
有的时候,数组中表示的可能是一些互相关联的元素,如果遇到了这些相互关联的元素中的一个,就将其他元素做一个标记的话,上面的引用肯定就不管用了。这时候修改这些关联元素的时候,就要使用其对应的键值了。先试试看管用不:

 代码如下 复制代码

$array = array("A"=>1, "B"=>1, "C"=>1, "D"=>1);
foreach($array as $key => $value){
    if($key == "B"){
        $array["A"] = "CHANGE";
        $array["D"] = "CHANGE";
        print_r($array);
        echo '
';
    }
 
    if($value === "CHANGE")
        echo $value.'
';
}
print_r($array);
?>

别着急看输出,我们想象中的应该是什么样呢?打印修改后的数组,打印一个“CHANGE”,再打印一遍修改后的数组。对吗?来看一下输出吧!

Array ( [A] => CHANGE [B] => 1 [C] => 1 [D] => CHANGE )
Array ( [A] => CHANGE [B] => 1 [C] => 1 [D] => CHANGE )
咦?怎么个情况?我们的CHANGE哪去了?

按照我们的想法,既然$array已经改变了,那么当遍历到键值为“D”的元素时,应当输出它的新值“CHANGE”才对!可是事实并不是我们想的那样。PHP在这里做了什么手脚呢?把上面的代码稍微修改一下。既然打印数组的时候,“D”=>CHANGE没错,那我们修改第二个if语句的判断条件:

 代码如下 复制代码

$array = array("A"=>1, "B"=>1, "C"=>1, "D"=>1);
foreach($array as $key => $value){
    if($key == "B"){
        $array["A"] = "CHANGE";
        $array["D"] = "CHANGE";
        print_r($array);
        echo '
';
    }
   
    if($array[$key] === "CHANGE")
        echo $value.'
';
}
print_r($array);
?>

猜猜它会输出什么?$value肯定不会等于“CHANGE”啦!难道等于1么?

 代码如下 复制代码
Array ( [A] => CHANGE [B] => 1 [C] => 1 [D] => CHANGE )
1
Array ( [A] => CHANGE [B] => 1 [C] => 1 [D] => CHANGE )

那么,它确实就是1了。

这究竟是神马原因呢?翻到PHP文档的foreach那页,恍然:

Note: 除非数组是被引用,foreach 所操作的是指定数组的一个拷贝,而不是该数组本身。foreach对数组指针有些副作用。除非对其重置,在 foreach 循环中或循环后都不要依赖数组指针的值。

原来foreach所操作的是指定数组的一个拷贝。怪不得,取$value不管用了呢!理解到这里,上面的问题就解决了。只要在foreach中,直接按照键取$array中的元素进行各种判断赋值操作就可以了。


总结及延伸
PHP的数组遍历和操作能力确实非常强大,然而对一些稍复杂问题的解决方法却不是那么明显。其实在任何领域都是这样,一个语言和语法提供的都是基本的操作,对于复杂的问题的解决办法都需要开发者自己的思考、想象力和代码编写来完成。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/631503.htmlTechArticle前面我讲过简单的数组遍历,这些基于foreach,for之类的语句,下面我来介绍数组的高级遍历方法介绍,各位朋友可参考,这些数组才真用于开...
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles