ホームページ  >  記事  >  バックエンド開発  >  PHPデータ構造拡張の詳しい説明

PHPデータ構造拡張の詳しい説明

coldplay.xixi
coldplay.xixi転載
2020-06-22 17:47:213146ブラウズ

PHPデータ構造拡張の詳しい説明

#免責事項: この記事は CC BY-NC-ND 4.0 に基づいてライセンスされています。

PHP でコレクションを表すデータ型は、配列という 1 つだけです。 PHP を初めて使用する人は皆、混乱すると思います。これは他の言語では配列またはリストのように見えるはずですが、PHP ではリストとマップの両方がすべてです:

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

これはいいですね。とにかく、全員が同じデータ構造を使用しています。場合によっては、パフォーマンスの問題が発生することがあります。さらに、PHP7 にアップグレードした後、Array のパフォーマンスも向上しました。良くない場合は、メモリを追加できます。 。しかし、より便利なデータ構造を導入することでパフォーマンスを最適化し、同時にコードの記述もより便利になるのであれば、そうしない手はないでしょうか?

推奨チュートリアル: "PHP チュートリアル "

Array の欠点

セット (Set) を保存する必要がある場合がありますが、Array では要素の一意性が保証されず、array_unique ではパフォーマンスの低下が避けられません。妥協案は、要素をキーとして使用し、値を true として使用して、Unique Array の機能を実現することです:

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

PHP の配列は、存在しないキーにアクセスすると null を取得する可能性があり、致命的なエラーは生成されませんが、E_NOTICE が発生します。この E_NOTICE は、set_error_handler によって登録された関数によってインターセプトされます。明らかに、この種の汚れたコードと不要なパフォーマンスのオーバーヘッドは完全に回避できます。

rree

array_key_exists と if else を使用してコードをすっきりさせることもできますが、冗長に見えます。

配列の一部の関数メソッド (array_map、array_walk など) は使用するのが難しく、書き方も醜いです。もちろん、ネイティブ PHP でこれを行う良い方法はありませんが、結局のところ、PHP のオブジェクト指向遺伝子はそれほど強力ではありません。

レリーレリー

場合によっては、次のコードのように、配列を使用するとパフォーマンスが非常に低下します1

何もないようかもしれませんが、配列は本質的にはマップであることに注意してください。要素のシフトを解除すると、各要素のキーが変更されます。これは $O(n)$ 操作です。さらに、PHP の配列はその値 (展開されたキーとそのハッシュを含む) をバケットに保存するため、各バケットを確認してハッシュを更新する必要があります。実際には、PHP は新しい配列を作成することで array_unshift 操作を内部で実行しますが、パフォーマンスの問題は想像できます

2

他にも多くの欠点があります。

PHP データ構造プラグイン

Array は批判されており、代替案が登場するでしょう。 PHP5 には spl がありますが、一部のシナリオではパフォーマンスが非常に低く、設計も非常に貧弱です

1。 Laravel のコレクションはより便利な Map を提供しますが、結局のところ、それは単一のデータ構造にすぎず、ORM 操作用に多くの独自のインターフェイスが設計されており、その使用は限定されています。

PHP7 の新しい Data Structures プラグイン (略して ds) は、PHP への次の優れた追加機能であり、利便性、セキュリティ、整頓性のニーズを十分に考慮しています。以下に示すように。

PHPデータ構造拡張の詳しい説明

これは、Collection、Sequence、Hashable の 3 つのインターフェイス クラスと、Vector、Deque、Map、Set、Stack、Queue、PriorityQueue の 7 つの実装クラス (最終クラス) を提供します。

Interface

Collection は基本的なインターフェイスで、foreach、json_encode、var_dump などのデータ コレクション (ここでのコレクションとは Set ではなく Collection を指します) の基本操作を定義します。

rree

Sequence は配列のようなデータ構造の基本インターフェイスであり、contains、map、filter、reduce、find、first、last などの多くの重要で便利なメソッドを定義します。図からわかるように、Vector、Deque、Stack、Queue はすべて、直接的または間接的にこのインターフェイスを実装しています。

rree

Hashable は図では孤立しているように見えますが、Map と Set にとって重要です。オブジェクトが Hashable を実装している場合、Map のキーや Set の要素として使用できます。このように、Map と Set は Java と同じように便利に使用できます。

実装クラス

Vector は最も一般的に使用されるデータ構造の 1 つであり、Ruby の Array または Python の List と考えることができます。要素の値のインデックスはバッファ内のインデックスとなるため、非常に効率的です。配列を使用する必要があり、挿入、削除、シフト、シフト解除を必要としない限り、これを使用できます。

Deque([dek]) は両端キューであり、Vector にヘッド ポインターを追加するため、シフトとシフト解除も $O(1)$ 複雑になります。ただし、パフォーマンスの低下はそれほど大きくないため、Deque は 1 つだけで十分で Vector は必要ないという議論もあります (議論)

3

Stack 栈,嗯没什么好说的,它继承自 Collection,但内部使用 Vector 实现。这样做的好处是实现方便,且同时可以屏蔽不需要的和不应该出现的方法。

Queue 队列,内部使用 Deque 实现。

PriorityQueue,最大堆实现。

Map。以前使用 Array 来实现 map 的地方,改用 Map 更好。二者性能几乎一致,但 Map 对内存的管理更好。而且,Map 的语法要更加友好。

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

$req = new \Ds\Map(["a" => 1, "b" => 2, "c" => 3]);
$req->get(&#39;user_id&#39;);// OutOfBoundsException
$req->get(&#39;user_id&#39;, 0); // 0 是默认值
// 即可以方便的指定默认值,也可以选择抛出异常。不用 array,不会产生 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 集合是一种元素唯一的数据结构。和 array_unique 相比性能有很大提升,而且用法也更加优雅1

<?php
$set = new Ds\Set();
$set->add($p1);
$set->add($p2);
   
  1. php ds 插件性能测试 ↩ ↩2  ↩3

  2. 当然,这一点可能稍嫌牵强,毕竟即使是数据量很大的情况下,array_unshift 的耗时也没有那么大 ↩

  3. github 上还在讨论可以增加一个不可变类型 Tuple,以及取消 Vector 直接使用 Deque,讨论地址和 2.0API 计划 ↩

以上がPHPデータ構造拡張の詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.imで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。