PHP中Array數(shù)據(jù)類型的介紹和應(yīng)用-創(chuàng)新互聯(lián)

今天就跟大家聊聊有關(guān)PHP中的Array數(shù)據(jù)類型,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

在柳河等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需求定制設(shè)計(jì),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),營(yíng)銷型網(wǎng)站建設(shè),成都外貿(mào)網(wǎng)站制作,柳河網(wǎng)站建設(shè)費(fèi)用合理。

在 PHP 中表示集合的數(shù)據(jù)類型就一種:Array。相信每個(gè)初學(xué) PHP 的都會(huì)對(duì)它感到疑惑。這個(gè)東西看起來(lái)應(yīng)該和其他語(yǔ)言中的 Array 或者 List 一樣,但在 PHP 中,它是一切,即是 List,也是 Map:

<?php
$a = array(1, 2, 3);
$b = array('key1' => 1, 'key2' => 2);

這聽(tīng)起來(lái)似乎很好,反正大家都使用同一種數(shù)據(jù)結(jié)構(gòu),偶爾情況下才會(huì)有些性能問(wèn)題,況且升級(jí) PHP7 之后 Array 的性能也提高了,實(shí)在不濟(jì)還可以加內(nèi)存。但如果我們可以通過(guò)引入更便利的數(shù)據(jù)結(jié)構(gòu)優(yōu)化性能,同時(shí)寫代碼反而更方便了,那何樂(lè)而不為呢?

Array 的缺點(diǎn)

有些時(shí)候我們需要保存一個(gè)集合(Set),但是 Array 并不能保證元素的唯一性,array_unique 有不可避免的性能損耗。一種折衷方案是,將元素當(dāng)做 key,同時(shí) value 為 true 來(lái)曲線實(shí)現(xiàn) Unique Array 的功能:

<?php
$users = User::find($ids);
$res = [];
foreach ($users as $user) {
  $res[$user->id] = true;
}

PHP 的 Array 訪問(wèn)不存在的 key 可以得到 null,不會(huì)產(chǎn)生 fatal error,但會(huì)有一個(gè) E_NOTICE。這個(gè) E_NOTICE 會(huì)被 set_error_handler 注冊(cè)的函數(shù)截獲。顯然,這種代碼上的不干凈和性能上的無(wú)謂開(kāi)銷完全是可以避免的。

<?php
$req = [];
$req['user_id']; // PHP Notice:  Undefined offset

可以用 array_key_exists 和 if else 來(lái)讓代碼干凈一些,但這樣就顯得啰嗦了。

array 的一些函數(shù)式方法很難用,比如 array_map, array_walk 等,寫起來(lái)也很丑陋。當(dāng)然這一點(diǎn)原生 PHP 沒(méi)什么好方法,畢竟 PHP 的面向?qū)ο蟮幕虿皇呛軓?qiáng)。

<?php
array_map(function($user){
  return $user->is_deleted();
}, $users);
// 就是這么難看
users.map { |user| user.is_deleted? }
# ruby 的就好看多了

在某些情況下,使用 Array 性能很差1,比如下面這段代碼:

<?php
$a=[1,2,3,4,5,6,7];
echo $a[5];
// 6
array_unshift($a, 0);
// $a: [0,1,2,3,4,5,6,7];
echo $a[5];
// 5

看起來(lái)似乎沒(méi)什么,但需要注意的是,Array 本質(zhì)上是一個(gè) Map,unshift 一個(gè)元素進(jìn)來(lái),將會(huì)改變每個(gè)元素的 key,這是一個(gè) $O(n)$ 操作。另外,PHP 的 Array 將其 value(包擴(kuò) key 和 它的 hash) 保存在一個(gè) bucket 中,所以我們需要查看每一個(gè) bucket 并更新 hash。PHP 內(nèi)部其實(shí)是通過(guò)創(chuàng)建新的 array 來(lái)做 array_unshift 操作的,其性能問(wèn)題可想可知2。

其他缺點(diǎn)不一而足。

PHP 數(shù)據(jù)結(jié)構(gòu)插件

Array 飽受詬病,就會(huì)出現(xiàn)替代方案。PHP5 有spl,但是有些場(chǎng)景性能很差,且設(shè)計(jì)的很不好1。laravel 的 Collection        提供了更好用的 Map,但畢竟只是一種單一的數(shù)據(jù)結(jié)構(gòu),而且對(duì) orm 操作設(shè)計(jì)了不少特有的接口,其用途受到限制。

PHP7 新增的 Data Structures 插件(簡(jiǎn)稱 ds)是 PHP 下一個(gè)優(yōu)秀的補(bǔ)充,它充分考慮了便利、安全和整潔的需求。如下圖所示。

PHP中Array數(shù)據(jù)類型的介紹和應(yīng)用

它提供了 3 個(gè)接口類:Collection, Sequence, Hashable 和 7 個(gè)實(shí)現(xiàn)類(final class):Vector, Deque, Map, Set, Stack, Queue, PriorityQueue。

接口

Collection 是基礎(chǔ)接口,定義了一個(gè)數(shù)據(jù)集合(這里的集合指的是 Collection,不是 Set) 的基本操作,比如 foreach, json_encode, var_dump 等。

<?php
$sequence = new \Ds\Vector([1, 2, 3]);
json_encode($sequence);

Sequence 是類數(shù)組數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)接口,定義了很多重要且方便的方法,比如 contains, map, filter, reduce, find, first, last 等。從圖中可知,Vector, Deque, Stack, Queue 都直接或者間接的實(shí)現(xiàn)了這個(gè)接口。

<?php
$sequence = new \Ds\Vector([1, 2, 3]);

print_r($sequence->map(function($value) { return $value * 2; }));
print_r($sequence);
?>

Hashable 在圖中看起來(lái)比較孤立,但對(duì)于 Map 和 Set 很重要。一個(gè) Object 如果實(shí)現(xiàn)了 Hashable,就可以作為 Map 的 key,可以作為 Set 的元素。這樣 Map 和 Set 就能像 Java 一樣方便的使用了。

實(shí)現(xiàn)類

Vector 應(yīng)該是最為常用的數(shù)據(jù)結(jié)構(gòu)之一了,可以把它當(dāng)成 Ruby 的 Array 或者 Python 的 List。其元素的值的 index 就是它在 buffer 中的 index,所以效率很高。只要有使用數(shù)組的需求且不需要 insert, remove, shift 和 unshift 的都可以用它。

Deque([dek]) 是雙端隊(duì)列,在 Vector 的基礎(chǔ)上增加了一個(gè)頭指針,因此 shift 和 unshift 也是 $O(1)$ 復(fù)雜度了。但帶來(lái)的性能損耗并不多,因此也有討論是不是只需要一個(gè) Deque 就夠了,不需要 Vector(討論)3。

Stack 棧,嗯沒(méi)什么好說(shuō)的,它繼承自 Collection,但內(nèi)部使用 Vector 實(shí)現(xiàn)。這樣做的好處是實(shí)現(xiàn)方便,且同時(shí)可以屏蔽不需要的和不應(yīng)該出現(xiàn)的方法。

Queue 隊(duì)列,內(nèi)部使用 Deque 實(shí)現(xiàn)。

PriorityQueue,大堆實(shí)現(xiàn)。

Map。以前使用 Array 來(lái)實(shí)現(xiàn) map 的地方,改用 Map 更好。二者性能幾乎一致,但 Map 對(duì)內(nèi)存的管理更好。而且,Map 的語(yǔ)法要更加友好。

<?php
$req = [];
$req['user_id']; // PHP Notice:  Undefined offset

$req = new \Ds\Map(["a" => 1, "b" => 2, "c" => 3]);
$req->get('user_id');// OutOfBoundsException
$req->get('user_id', 0); // 0 是默認(rèn)值
// 即可以方便的指定默認(rèn)值,也可以選擇拋出異常。不用 array,不會(huì)產(chǎn)生 E_NOTICE

$req->keys();

$req->map(function($key, $value) { return $value * 2; });

不僅如此,只要 object 繼承了 Hashable,Map 還允許使用 object 作為 key。

<?php
class Photo implements \Ds\Hashable {
    
    public function __construct($id) {
        $this->id = $id;
    }
    
    public function hash() {
        return $this->id;
    }

    public function equals($obj): bool {
        return $this->id === $obj->id;
    }
}

$p1 = new Photo(1);
$p2 = new Photo(2);

$map = new Ds\Map();
$map->put($p1, 1);
$map->put($p2, 2);

Set 集合是一種元素唯一的數(shù)據(jù)結(jié)構(gòu)。和 array_unique 相比性能有很大提升,而且用法也更加優(yōu)雅1。

<?php
$set = new Ds\Set();
$set->add($p1);
$set->add($p2);
  1. php ds 插件性能測(cè)試 ? ?2  ?3

  2. 當(dāng)然,這一點(diǎn)可能稍嫌牽強(qiáng),畢竟即使是數(shù)據(jù)量很大的情況下,array_unshift 的耗時(shí)也沒(méi)有那么大 ?

  3. github 上還在討論可以增加一個(gè)不可變類型 Tuple,以及取消 Vector 直接使用 Deque,討論地址和 2.0API 計(jì)劃 ?

看完上述內(nèi)容,你們對(duì)PHP中Array數(shù)據(jù)類型有進(jìn)一步的了解嗎?如果還想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝各位的閱讀。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

分享文章:PHP中Array數(shù)據(jù)類型的介紹和應(yīng)用-創(chuàng)新互聯(lián)
文章URL:http://muchs.cn/article30/dhdppo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站、微信公眾號(hào)、網(wǎng)站導(dǎo)航、軟件開(kāi)發(fā)、響應(yīng)式網(wǎng)站、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)