PHP是否有内置数据结构?

69

我正在查看 PHP 手册,但是我没有看到大多数编程语言都有的数据结构部分,例如列表和集合。我是瞎了还是 PHP 没有内置这样的东西?


非常适用于PHP 4;自PHP 5以来不再实际。 - Alex Shesterov
1
有一个GitHub项目,它扩展了PHP7的数据结构支持。包括MAP、SET等。请查看开发者主页并检查GitHub项目 - Werner
10个回答

62

9
PHP数组实际上是一种有序字典。它可以用于表示数组、列表、队列、栈、树,甚至是图形,使用引用时还可以进行更多操作。而且它速度快。你还能想要什么呢? - Kamil Szot
它支持地图吗? - newday
2
@newday:“Ordered Dictionary”意味着“映射”。 - Sebastian Mach
1
自 PHP7 开始,数据结构有更好的扩展 - DS https://stackoverflow.com/a/61698578/7082164 - Jsowa

37

PHP提供数据结构通过标准 PHP 库 (SPL) 基本扩展,PHP 5.0.0 默认编译安装。

可用于 PHP 5 >= 5.3.0 的数据结构包括:

双向链表

双向链表 (DLL) 是一组节点互相链接的链表,每个节点都有两个方向。当底层结构是 DLL 时,迭代器操作、访问两端、添加或移除节点的成本为 O(1)。因此,它为栈和队列提供了一个不错的实现。

堆是类似于树状结构的结构,遵循堆属性:每个节点都大于或等于其子节点,使用实现的 compare 方法进行比较(对于堆来说该方法是全局的)。

数组

数组是以连续方式存储数据的结构,可以通过索引访问。不要将它们与 PHP 数组混淆:实际上,PHP 数组被实现为有序哈希表。

映射

映射是一种存储键-值对的数据结构。PHP数组可以被看作是从整数/字符串到值的映射。SPL提供了一个从对象到数据的映射。这个映射也可以用作对象集。

来源:http://php.net/manual/zh/spl.datastructures.php


SPL数据结构速度较慢,您可能需要考虑@RanajanaLK的答案。 - John Hunt
和什么相比较慢,@JohnHunt? - Frederik Krautwald
与Ds相比较慢。 - John Hunt

24

PHP 7引入了一个名为ds的扩展,提供了专门的数据结构作为数组的替代方案。

ds使用Ds\命名空间。

  • 它有3个接口,分别是CollectionSequenceHashable
  • 它有8个类,分别是VectorDequeQueuePriorityQueueMapSetStackPair

更多信息请查看手册,此外这篇博客文章也有一些不错的信息和基准测试。


1
如果扩展未启用,Composer中还提供了一个polyfill来支持这些功能。我们使用DS和polyfill以防扩展未在服务器上启用 - 它的效果非常好,而且启用扩展后速度更快。 - John Hunt

16

关联数组可用于大多数基本数据结构哈希表、队列、栈。但如果您需要像树或堆这样的内容,我认为它们不会默认存在,但我确定有免费的库可以使用。

要让数组模拟栈,请使用array_push()添加元素和array_pop()弹出元素。

要让数组模拟队列,请使用array_push()将元素入队和array_shift()将元素出队。

PHP中的关联数组默认为哈希表,它们允许使用字符串作为索引,因此以下操作按预期工作:

$array['key'] = 'value';

最后,你可以使用一个数组来模拟二叉树,但这样可能会浪费一些空间。如果你知道你的树很小,那么这种方法就很有用了。使用线性数组,你可以说对于任何索引(i),你将它的左子节点放在索引(2i+1)处,右子节点放在索引(2i+2)处。

所有这些方法都在这篇文章中得到了很好地阐述,该文章介绍如何使用JavaScript数组模拟更高级别的数据结构。


8

PHP有数组,实际上是关联数组,也可以用作集合。与许多解释型语言一样,PHP在一个包中提供了所有这些功能,而不是提供不同的显式数据类型。

例如:

$lst = array(1, 2, 3);
$hsh = array(1 => "This", 2 => "is a", 3 => "test");

此外,可以参考手册了解更多有关数组的信息。

7

PHP的数组既可以作为列表,也可以作为字典。

(PHP的array可以同时作为list和dictionary。)
$myArray = array("Apples", "Oranges", "Pears");
$myScalar = $myArray[0] // == "Apples"

或者将其用作关联数组:

$myArray = array("a"=>"Apples", "b"=>"Oranges", "c"=>"Pears");
$myScalar = $myArray["a"] // == "Apples"

5

3

如果您感觉PHP没有特定类型的数据结构,您可以随时创建自己的数据结构。例如,这里有一个简单的基于数组的Set数据结构。

class ArraySet
{
    /** Elements in this set */
    private $elements;

    /** the number of elements in this set */
    private $size = 0;

    /**
     * Constructs this set.
     */ 
    public function ArraySet() {
        $this->elements = array();
    }

    /**
     * Adds the specified element to this set if 
     * it is not already present.
     * 
     * @param any $element
     *
     * @returns true if the specified element was
     * added to this set.
     */
    public function add($element) {
        if (! in_array($element, $this->elements)) {
            $this->elements[] = $element;
            $this->size++;
            return true;
        }
        return false;
    }

    /**
     * Adds all of the elements in the specified 
     * collection to this set if they're not already present.
     * 
     * @param array $collection
     * 
     * @returns true if any of the elements in the
     * specified collection where added to this set. 
     */ 
    public function addAll($collection) {
        $changed = false;
        foreach ($collection as $element) {
            if ($this->add($element)) {
                $changed = true;
            }
        }
        return $changed;
    }

    /**
     * Removes all the elements from this set.
     */ 
    public function clear() {
        $this->elements = array();
        $this->size = 0;
    }

    /**
     * Checks if this set contains the specified element. 
     * 
     * @param any $element
     *
     * @returns true if this set contains the specified
     * element.
     */ 
    public function contains($element) {
        return in_array($element, $this->elements);
    }

    /**
     * Checks if this set contains all the specified 
     * element.
     * 
     * @param array $collection
     * 
     * @returns true if this set contains all the specified
     * element. 
     */ 
    public function containsAll($collection) {
        foreach ($collection as $element) {
            if (! in_array($element, $this->elements)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Checks if this set contains elements.
     * 
     * @returns true if this set contains no elements. 
     */ 
    public function isEmpty() {
        return count($this->elements) <= 0;
    }

    /**
     * Get's an iterator over the elements in this set.
     * 
     * @returns an iterator over the elements in this set.
     */ 
    public function iterator() {
        return new SimpleIterator($this->elements);
    }

    /**
     * Removes the specified element from this set.
     * 
     * @param any $element
     *
     * @returns true if the specified element is removed.
     */ 
    public function remove($element) {
        if (! in_array($element, $this->elements)) return false;

        foreach ($this->elements as $k => $v) {
            if ($element == $v) {
                unset($this->elements[$k]);
                $this->size--;
                return true;
            }
        }       
    }

    /**
     * Removes all the specified elements from this set.
     * 
     * @param array $collection
     *
     * @returns true if all the specified elemensts
     * are removed from this set. 
     */ 
    public function removeAll($collection) {
        $changed = false;
        foreach ($collection as $element) {
            if ($this->remove($element)) {
                $changed = true;
            } 
        }
        return $changed;
    }

    /**
     * Retains the elements in this set that are
     * in the specified collection.  If the specified
     * collection is also a set, this method effectively
     * modifies this set into the intersection of 
     * this set and the specified collection.
     * 
     * @param array $collection
     *
     * @returns true if this set changed as a result
     * of the specified collection.
     */ 
    public function retainAll($collection) {
        $changed = false;
        foreach ($this->elements as $k => $v) {
            if (! in_array($v, $collection)) {
                unset($this->elements[$k]);
                $this->size--;
                $changed = true;
            }
        }
        return $changed;
    }

    /**
     * Returns the number of elements in this set.
     * 
     * @returns the number of elements in this set.
     */ 
    public function size() {
        return $this->size; 
    }

    /**
     * Returns an array that contains all the 
     * elements in this set.
     * 
     * @returns an array that contains all the 
     * elements in this set.
     */ 
    public function toArray() {
        $elements = $this->elements;
        return $elements;   
    }
}

1
不再在 GitHub 上线。 - Kzqai

3
当然,PHP有数据结构。PHP中的数组非常灵活。以下是一些示例:
$foo = array(
  'bar' => array(1,'two',3),
  'baz' => explode(" ", "Some nice words")
);

如果你需要对数组进行映射、筛选、遍历等操作,或者进行转换、翻转等操作,那么有大量的数组函数可供使用。


1
PHP也可以拥有一个"数组的数组",称为"多维数组"或"矩阵"。你可以拥有2维数组、3维数组等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接